BSOne.SFC/EM.Lib/ImageEn_SRC/Source/iexRulers.pas

4038 lines
117 KiB
Plaintext

(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *)
(*
Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved.
Copyright (c) 2011-2017 by Xequte Software.
This software comes without express or implied warranty.
In no case shall the author be liable for any damage or unwanted behavior of any
computer hardware and/or software.
Author grants you the right to include the component
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE.
ImageEn, IEvolution and ImageEn ActiveX may not be included in any
commercial, shareware or freeware libraries or components.
www.ImageEn.com
*)
(*
File: iexRulers.pas
Description: Provides rulers for use by TImageEnView and TRulerBox
File version 1010
Doc revision 1002
*)
unit iexRulers;
{$R-}
{$Q-}
{$I ie.inc}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
{$ifdef IEHASTYPES} Types, {$endif}
iegdiplus;
const
IEMAXPOLYGLINES = 10;
type
TIEPolyg = array[0..IEMAXPOLYGLINES - 1] of TPoint;
{!!
<FS>TGripKind
<FM>Declaration<FC>
TGripKind = (gkTriangle, gkLeftTriangle, gkRightTriangle, gkArrow, gkArrow2, gkLine, gkNone);
<FM>Description<FN>
<TABLE>
<R> <H>Item</H> <H>Description</H> </R>
<R> <C><FC>gkTriangle<FN></C> <C>Triangle</C> </R>
<R> <C><FC>gkLeftTriangle<FN></C> <C>Triangle pointing to the left</C> </R>
<R> <C><FC>gkRightTriangle<FN></C> <C>Triangle pointing to the right</C> </R>
<R> <C><FC>gkArrow<FN></C> <C>A standard arrow</C> </R>
<R> <C><FC>gkArrow2<FN></C> <C>A track bar style arrow</C> </R>
<R> <C><FC>gkLine<FN></C> <C>Line only</C> </R>
<R> <C><FC>gkNone<FN></C> <C>Grip is not visible</C> </R>
</TABLE>
!!}
TGripKind = (gkTriangle, gkLeftTriangle, gkRightTriangle, gkArrow, gkArrow2, gkLine, gkNone);
{!!
<FS>TGripsDir
<FM>Declaration<FC>
}
TGripsDir = (gdUp, gdDown);
{!!}
{!!
<FS>TGripsXDir
<FM>Declaration<FC>
}
TGripsXDir = (gdLeft, gdRight);
{!!}
{!!
<FS>TRulerDir
<FM>Declaration<FC>
}
TRulerDir = (rdHorizontal, rdVertical);
{!!}
{!!
<FS>TRulerDirs
<FM>Declaration<FC>
TRulerDirs = Set of <A TRulerDir>;
!!}
TRulerDirs = Set of TRulerDir;
{!!
<FS>TIERulerUnits
<FM>Declaration<FC>
}
TIERulerUnits = (ieruPixels, ieruInches, ieruMillimeters, ieruCentimeters);
{!!}
{!!
<FS>TIERulerSnapping
<FM>Declaration<FC>
TIERulerSnapping = (iesnNone, iesnSnapToTick, iesnSnapToLabel, iesnSnapToWholeNumber);
<FM>Description<FN>
<TABLE>
<R> <H>Item</H> <H>Description</H> </R>
<R> <C><FC>iesnNone<FN></C> <C>Do not adjust grip positions</C> </R>
<R> <C><FC>iesnSnapToTick<FN></C> <C>Automatically move grips to the nearest <L TIEViewRulerParams.Frequency>tick</L></C> </R>
<R> <C><FC>iesnSnapToLabel<FN></C> <C>Automatically move grips to the nearest <L TIEViewRulerParams.LabelFrequency>label</L> (long tick)</C> </R>
<R> <C><FC>iesnSnapToWholeNumber<FN></C> <C>Automatically move grips to the nearest whole value on the ruler (e.g. move to 2.0 inches)</C> </R>
</TABLE>
Default: iesnNone
<FM>Example<FC>
// Snap to the nearest label tick
ImageEnView1.RulerParams.SnapGrips := iesnSnapToLabel;
// Snap to the nearest whole number on the ruler
ImageEnView1.RulerParams.SnapGrips := iesnSnapToWholeNumber;
!!}
TIERulerSnapping = (iesnNone, iesnSnapToTick, iesnSnapToLabel, iesnSnapToWholeNumber);
{!!
<FS>TIERulerPosBase
<FM>Declaration<FC>
}
TIERulerPosBase = (ierbRuler, ierbBitmap, ierbScreen);
{!!}
{!!
<FS>TRulerGripPosChangeEvent
<FM>Declaration<FC>
}
TRulerGripPosChangeEvent = procedure(Sender: TObject; RulerDir: TRulerDir; Grip: integer; NewPos: Double) of object;
{!!}
{!!
<FS>TRulerClickEvent
<FM>Declaration<FC>
}
TRulerClickEvent = procedure(Sender: TObject; RulerDir: TRulerDir; Ps: double) of object;
{!!}
{!!
<FS>TRulerGripClickEvent
<FM>Declaration<FC>
}
TRulerGripClickEvent = procedure(Sender: TObject; RulerDir: TRulerDir; Grip: integer; GripPos: Double) of object;
{!!}
// Internal only
TRulerSetGripPosEvent = procedure(Sender: TObject; var GripPos: double) of object;
// Internal class for handling and display the rulers of TImageEnView and TRulerBox
TIERuler = class
private
{ Private declarations }
fOwner: TControl;
fBitmap: TBitmap;
fBackground: TColor;
fGrips: TList; // list of rips
fGripBaseDim: integer; // base size of grip (triangles)
fSelGrip: integer; // selected grip (-1=none)
fSelGripSt: integer; // starting position during mouse-dragging
fMX1, fMY1: integer; // initial mouse coordinate during mouse-dragging
fGripsDir: TGripsDir; // direction for all grips
fShowRuler: boolean; // ruler + numeric labels
fViewPos: double; // starting ruler position
fDPU: double; // DotPerUnit - relation between ruler and pixels
fFrequency: double; // line frequency (Unit based)
fLabelFreq: double; // label frequency (Unit based)
fRulerColor: TColor; // ruler color
fRulerDir: TRulerDir; // ruler orientation
fViewMin, fViewMax: double; // Max and Min for fViewPos
fFitInView: boolean; // adjust fDPU from fViewMin and fViewMax
fHexLabels: boolean; // if true display labels in hex
fMaxGripHeight: integer;
fInverted: boolean; // ruler is inverted
fScrollRate: double; // scroll rate
fOffsetX, fOffsetY: integer; // horizontal or vertical offset
fLabelPrecision: Integer;
fMinLabelSpacing: Integer;
fGripPenColor : TColor;
fGripKindDefault: TGripKind;
fGripColorDefault : TColor;
fLockUpdateCount: Integer; // When > 0 updating is disabled
fFont: TFont;
fGripIndexOffset: Integer; // When used by a TImageEnView, grip 0 is used to show the cursor position. We hide this from the user by offsetting the grip indexes/count by 1
fShowBorder: Boolean;
procedure SetBackground(bk: TColor);
procedure SetGripsCount(v: integer);
function GetGripsCount: integer;
procedure SetGripsPos(i: integer; p: double);
function GetGripsPos(i: integer): double;
procedure SetGripsColor(i: integer; p: TColor);
function GetGripsColor(i: integer): TColor;
procedure SetGripBaseDim(v: integer);
procedure SetGripsKind(i: integer; v: TGripKind);
function GetGripsKind(i: integer): TGripKind;
procedure SetGripsDir(v: TGripsDir);
procedure SetShowRuler(v: boolean);
procedure SetViewPos(v: double);
procedure SetDPU(v: double);
procedure SetFrequency(v: double);
procedure SetLabelFreq(v: double);
procedure SetRulerColor(v: TColor);
procedure SetRulerDir(v: TRulerDir);
procedure SetGripsMax(i: integer; v: double);
procedure SetGripsMin(i: integer; v: double);
function GetGripsMax(i: integer): double;
function GetGripsMin(i: integer): double;
procedure SetViewMin(v: double);
procedure SetViewMax(v: double);
procedure SetFitInView(v: boolean);
procedure SetHexLabels(v: boolean);
procedure SetInverted(v: boolean);
procedure SetOffsetX(v: integer);
procedure SetOffsetY(v: integer);
procedure SetLabelPrecision(v: integer);
procedure SetMinLabelSpacing(v: integer);
procedure SetGripPenColor(const Value: TColor);
procedure SetGripKindDefault(const Value: TGripKind);
procedure SetGripColorDefault(const Value: TColor);
function GetClickedGrip(x, y: integer): integer;
procedure GetGripPoly(gn: integer; var poly: TIEPolyg);
procedure GetGripRect(gn: integer; var rc: TRect);
function GetRulerHeight: integer;
procedure RepaintGrips;
procedure RepaintRuler;
procedure RepaintBorder;
function GetXGripPos(gn: integer): integer;
procedure AdjustGripLimits(gn: integer);
procedure AdjustViewLimits;
procedure SetShowBorder(const Value: boolean);
protected
{ Protected declarations }
procedure FontChange(Sender: TObject);
public
{ Public declarations }
// EVENTS
fOnRulerGripPosChange: TRulerGripPosChangeEvent;
fOnRulerGripClick: TRulerGripClickEvent;
fOnRulerGripDblClick: TRulerGripClickEvent;
fOnRulerClick: TRulerClickEvent;
constructor Create(Owner: TControl);
destructor Destroy; override;
procedure Update();
procedure UpdateEx(RepaintAll, DoInvalidate : Boolean);
procedure LockUpdate();
procedure UnlockUpdate(RepaintAll: Boolean = True; DoInvalidate: Boolean = True);
property GripsPos[g: integer]: double read GetGripsPos write SetGripsPos; default;
property GripsColor[g: integer]: TColor read GetGripsColor write SetGripsColor;
property GripsKind[g: integer]: TGripKind read GetGripsKind write SetGripsKind;
property GripsMin[g: integer]: double read GetGripsMin write SetGripsMin;
property GripsMax[g: integer]: double read GetGripsMax write SetGripsMax;
property ScrollRate: double read fScrollRate write fScrollRate;
// Need to handle the following in objects that use this class
procedure DrawToCanvas(Canvas: TCanvas; X, Y: Integer);
procedure HandleMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure HandleMouseMove(Shift: TShiftState; X, Y: Integer);
procedure HandleMouseMoveEx(Shift: TShiftState; X, Y: Integer; SetGripCallBack: TRulerSetGripPosEvent);
procedure HandleMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure UpdateSize(Width, Height: integer);
property ViewPos: double read fViewPos write SetViewPos;
property Background: TColor read fBackground write SetBackground default clBtnFace;
property GripPenColor : TColor read fGripPenColor write SetGripPenColor default clWindowFrame;
property GripBaseDim: integer read fGripBaseDim write SetGripBaseDim default 12;
property GripsDir: TGripsDir read fGripsDir write SetGripsDir default gdUp;
property ShowRuler: boolean read fShowRuler write SetShowRuler default true;
property DotPerUnit: double read fDPU write SetDPU;
property Frequency: double read fFrequency write SetFrequency;
property LabelFrequency: double read fLabelFreq write SetLabelFreq;
property RulerColor: TColor read fRulerColor write SetRulerColor default clBtnFace;
property RulerDir: TRulerDir read fRulerDir write SetRulerDir default rdHorizontal;
property ViewMin: double read fViewMin write SetViewMin;
property ViewMax: double read fViewMax write SetViewMax;
property LabelPrecision: integer read fLabelPrecision write SetLabelPrecision default 3;
property MinLabelSpacing: integer read fMinLabelSpacing write SetMinLabelSpacing default 30;
property GripKindDefault: TGripKind read fGripKindDefault write SetGripKindDefault default gkTriangle;
property GripColorDefault: TColor read fGripColorDefault write SetGripColorDefault default clBtnFace;
property OffsetX: integer read fOffsetX write SetOffsetX default 0;
property OffsetY: integer read fOffsetY write SetOffsetY default 0;
property MaxGripHeight: integer read fMaxGripHeight write fMaxGripHeight;
property Inverted: boolean read fInverted write SetInverted default false;
property FitInView: boolean read fFitInView write SetFitInView default false;
property GripsCount: integer read GetGripsCount write SetGripsCount default 1;
property HexLabels: boolean read fHexLabels write SetHexLabels default false;
property ShowBorder : boolean read fShowBorder write SetShowBorder default False;
property LockUpdateCount: integer read fLockUpdateCount;
property SelectedGrip: integer read fSelGrip write fSelGrip;
property Font: TFont read fFont;
end;
{!!
<FS>TIEViewRulerParams
<FM>Description<FN>
Specifies the <L TImageEnView.RulerParams>properties of embedded rulers</L> within a TImageEnView (if <A TImageEnView.ShowRulers> is not []).
<FM>Example<FC>
// Show rulers in TImageEnView
ImageEnView1.ShowRulers := [ rdHorizontal, rdVertical ];
// Set units to CM
ImageEnView1.RulerParams.Units := ieruCentimeters;
// Show grips as a line
ImageEnView1.RulerParams.Units := gkLine;
<FM>Methods and Properties<FN>
<FI>Display<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.AlignToImage></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.Color></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.Frequency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.Font></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzInverted></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzPos></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.LabelFrequency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.LabelPrecision></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.MinLabelSpacing></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.MeasureColor></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.ShowMeasure></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.ShowBorder></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.Units></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertInverted></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertPos></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertWidth></C> </R>
</TABLE>
<FI>Grip Properties<FN>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.ConstrainGrips></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.CursorGripKind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.GripHeight></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.GripWidth></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.GripColorDefault></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.GripKindDefault></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.GripPenColor></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzGripsColor></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzGripsCount></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzGripsKind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzGripsMax></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzGripsMin></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.HorzGripsPos></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.SnapGrips></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertGripsColor></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertGripsCount></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertGripsKind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertGripsMax></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertGripsMin></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.VertGripsPos></C> </R>
</TABLE>
<FI>Other<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIEViewRulerParams.ScrollRate></C> </R>
</TABLE>
<FM>Events<FN>
<TABLE2>
<R> <C_IMG_EVENT> <C><A TImageEnView.OnRulerClick></C> </R>
<R> <C_IMG_EVENT> <C><A TImageEnView.OnRulerGripClick></C> </R>
<R> <C_IMG_EVENT> <C><A TImageEnView.OnRulerGripDblClick></C> </R>
<R> <C_IMG_EVENT> <C><A TImageEnView.OnRulerGripPosChange></C> </R>
</TABLE>
!!}
TIEViewRulerParams = class
private
{ Private declarations }
fOwner: TControl;
fHorzRuler: TIERuler;
fVertRuler: TIERuler;
fSnapGrips: TIERulerSnapping;
fConstrainGrips: Boolean;
fAlignToImage: Boolean;
fUnits: TIERulerUnits;
fWasUnits: TIERulerUnits;
fHorzPos: TGripsDir;
fVertPos: TGripsXDir;
fHorzHeight : Integer;
fVertWidth : Integer;
fGripsPosBase: TIERulerPosBase;
// Limit duplicate paints caused by the MouseMove handling
fLastMouseMoveX : Integer;
fLastMouseMoveY : Integer;
fLastMouseMoveShift : TShiftState;
fLastMouseMoveResult: Boolean;
function GetHorzGripsPos(i: integer): double;
procedure SetHorzGripsPos(i: integer; p: double);
function GetHorzGripsColor(i: integer): TColor;
procedure SetHorzGripsColor(i: integer; p: TColor);
function GetHorzGripsMin(i: integer): double;
procedure SetHorzGripsMin(i: integer; v: double);
function GetHorzGripsMax(i: integer): double;
procedure SetHorzGripsMax(i: integer; v: double);
function GetVertGripsPos(i: integer): double;
procedure SetVertGripsPos(i: integer; p: double);
function GetVertGripsColor(i: integer): TColor;
procedure SetVertGripsColor(i: integer; p: TColor);
function GetVertGripsMin(i: integer): double;
procedure SetVertGripsMin(i: integer; v: double);
function GetVertGripsMax(i: integer): double;
procedure SetVertGripsMax(i: integer; v: double);
function GetMinLabelSpacing: integer;
procedure SetMinLabelSpacing(v: integer);
function GetFrequency: double;
procedure SetFrequency(v: double);
function GetLabelFrequency: double;
procedure SetLabelFrequency(v: double);
function GetShowMeasure: boolean;
procedure SetShowMeasure(v: boolean);
function GetMeasureColor: TColor;
procedure SetMeasureColor(v: TColor);
function GetColor: TColor;
procedure SetColor(c: TColor);
function GetHorzInverted: boolean;
procedure SetHorzInverted(v: boolean);
function GetVertInverted: boolean;
procedure SetVertInverted(v: boolean);
function GetLabelPrecision: integer;
procedure SetLabelPrecision(v: integer);
function GetScrollRate: double;
procedure SetScrollRate(const Value: double);
function GetCursorGripKind: TGripKind;
procedure SetCursorGripKind(const Value: TGripKind);
function GetGripKindDefault: TGripKind;
procedure SetGripKindDefault(const Value: TGripKind);
function GetGripColorDefault: TColor;
procedure SetGripColorDefault(const Value: TColor);
function GetGripPenColor: TColor;
procedure SetGripPenColor(const Value: TColor);
function GetHorzGripsCount: integer;
procedure SetHorzGripsCount(v: integer);
function GetHorzGripsKind(i: integer): TGripKind;
procedure SetHorzGripsKind(i: integer; v: TGripKind);
function GetVertGripsCount: integer;
procedure SetVertGripsCount(v: integer);
function GetVertGripsKind(i: integer): TGripKind;
procedure SetVertGripsKind(i: integer; v: TGripKind);
function GetGripWidth: integer;
procedure SetGripWidth(v: integer);
function GetGripHeight: integer;
procedure SetGripHeight(const Value: integer);
function GetFont: TFont;
procedure FontChange(Sender: TObject);
procedure SetSnapGrips(Value: TIERulerSnapping);
procedure SetConstrainGrips(Value: Boolean);
procedure SetAlignToImage(Value: Boolean);
procedure SetUnits(Value: TIERulerUnits);
procedure SetHorzPos(Value: TGripsDir);
procedure SetVertPos(Value: TGripsXDir);
procedure SetVertWidth(Value: Integer);
procedure SetHorzHeight(Value: Integer);
function GetHorzRulerRect: TRect;
function GetVertRulerRect: TRect;
procedure MouseMoveOutsideRuler(Shift: TShiftState; X, Y: Integer);
procedure ConstrainGripsCB(Sender: TObject; var GripPos: double);
procedure CheckGripBounds();
function ImageLeftOnHorzRuler(): double;
function ImageRightOnHorzRuler(): double;
function ImageTopOnVertRuler(): double;
function ImageBottomOnVertRuler(): double;
function ApplyHorzConstraints(value : double; DoSnapGrips : TIERulerSnapping = iesnNone; DoConstrainGrips : Boolean = False) : double;
function ApplyVertConstraints(value : double; DoSnapGrips : TIERulerSnapping = iesnNone; DoConstrainGrips : Boolean = False) : double;
function ScrToRulerX(X : Integer) : double;
function RulerToScrX(Pos : Double) : Integer;
function ScrToRulerY(Y : Integer) : double;
function RulerToScrY(Pos : Double) : Integer;
function ValueToRulerX(Value : double; ValueBase: TIERulerPosBase) : double;
function RulerToValueX(Pos : double; ValueBase: TIERulerPosBase) : double;
function ValueToRulerY(Value : double; ValueBase: TIERulerPosBase) : double;
function RulerToValueY(Pos : Double; ValueBase: TIERulerPosBase) : Double;
function HorzRulerVisible: Boolean;
function VertRulerVisible: Boolean;
procedure LockUpdate();
procedure UnlockUpdate(DoUpdate: Boolean = True; DoInvalidate: Boolean = True);
function GetOnRulerClick: TRulerClickEvent;
function GetOnRulerGripClick: TRulerGripClickEvent;
function GetOnRulerGripDblClick: TRulerGripClickEvent;
function GetOnRulerPosChange: TRulerGripPosChangeEvent;
procedure SetOnRulerClick(const Value: TRulerClickEvent);
procedure SetOnRulerGripClick(const Value: TRulerGripClickEvent);
procedure SetOnRulerGripDblClick(const Value: TRulerGripClickEvent);
procedure SetOnRulerPosChange(const Value: TRulerGripPosChangeEvent);
function GetShowBorder: boolean;
procedure SetShowBorder(const Value: boolean);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(Owner: TControl);
destructor Destroy; override;
property HorzGripsPos[g: integer]: double read GetHorzGripsPos write SetHorzGripsPos;
property HorzGripsColor[g: integer]: TColor read GetHorzGripsColor write SetHorzGripsColor;
property HorzGripsKind[g: integer]: TGripKind read GetHorzGripsKind write SetHorzGripsKind;
property HorzGripsMin[g: integer]: double read GetHorzGripsMin write SetHorzGripsMin;
property HorzGripsMax[g: integer]: double read GetHorzGripsMax write SetHorzGripsMax;
property VertGripsPos[g: integer]: double read GetVertGripsPos write SetVertGripsPos;
property VertGripsColor[g: integer]: TColor read GetVertGripsColor write SetVertGripsColor;
property VertGripsKind[g: integer]: TGripKind read GetVertGripsKind write SetVertGripsKind;
property VertGripsMin[g: integer]: double read GetVertGripsMin write SetVertGripsMin;
property VertGripsMax[g: integer]: double read GetVertGripsMax write SetVertGripsMax;
property ScrollRate: double read GetScrollRate write SetScrollRate;
property Color: TColor read GetColor write SetColor default clBtnFace;
property GripPenColor : TColor read GetGripPenColor write SetGripPenColor default clWindowFrame;
property GripWidth: integer read GetGripWidth write SetGripWidth default 12;
property GripHeight: integer read GetGripHeight write SetGripHeight;
property ShowMeasure: boolean read GetShowMeasure write SetShowMeasure default true;
property Frequency: double read GetFrequency write SetFrequency;
property LabelFrequency: double read GetLabelFrequency write SetLabelFrequency;
property MeasureColor: TColor read GetMeasureColor write SetMeasureColor default clBtnFace;
property LabelPrecision: integer read GetLabelPrecision write SetLabelPrecision default 3;
property MinLabelSpacing: integer read GetMinLabelSpacing write SetMinLabelSpacing default 30;
property CursorGripKind: TGripKind read GetCursorGripKind write SetCursorGripKind default gkLine;
property GripKindDefault: TGripKind read GetGripKindDefault write SetGripKindDefault default gkTriangle;
property GripColorDefault: TColor read GetGripColorDefault write SetGripColorDefault default cl3DLight;
property HorzGripsCount: integer read GetHorzGripsCount write SetHorzGripsCount default 1;
property VertGripsCount: integer read GetVertGripsCount write SetVertGripsCount default 1;
property HorzPos: TGripsDir read fHorzPos write SetHorzPos default gdUp;
property VertPos: TGripsXDir read fVertPos write SetVertPos default gdLeft;
property HorzInverted: boolean read GetHorzInverted write SetHorzInverted default false;
property VertInverted: boolean read GetVertInverted write SetVertInverted default false;
property ShowBorder : boolean read GetShowBorder write SetShowBorder default True;
{!!
<FS>TIEViewRulerParams.GripsPosBase
<FM>Declaration<FC>
property GripsPosBase: <A TIERulerPosBase>;
<FM>Description<FN>
Specifies the type of values used for grip position properties: <A TIEViewRulerParams.HorzGripsPos>, <A TIEViewRulerParams.VertGripsPos>, <A TIEViewRulerParams.HorzGripsMin>, <A TIEViewRulerParams.HorzGripsMax>, <A TIEViewRulerParams.VertGripsMin> and <A TIEViewRulerParams.VertGripsMax>.
The following options are available:
<TABLE>
<R> <H>Item</H> <H>Description</H> </R>
<R> <C><FC>ierbRuler<FN></C> <C>Values are ruler values (taking into account the DPI set by <A TIEViewRulerParams.Units> </C> </R>
<R> <C><FC>ierbBitmap<FN></C> <C>Values are pixel positions on the currently displayed image (regardless of zoom, scrolling, etc)</C> </R>
<R> <C><FC>ierbScreen<FN></C> <C>Values are screen values</C> </R>
</TABLE>
Default: ierbBitmap
<FM>Example<FC>
// Add three grips at 25%, 50% and 75% of the image width
ImageEnView1.RulerParams.HorzGripsCount := 3;
ImageEnView1.RulerParams.GripsPosBase := ierbBitmap; // Units are relative to the bitmap
ImageEnView1.RulerParams.HorzGripsPos[ 0 ] := MulDiv( ImageEnView1.IEBitmap.Width, 1, 4 );
ImageEnView1.RulerParams.HorzGripsPos[ 1 ] := MulDiv( ImageEnView1.IEBitmap.Width, 2, 4 );
ImageEnView1.RulerParams.HorzGripsPos[ 2 ] := MulDiv( ImageEnView1.IEBitmap.Width, 3, 4 );
!!}
property GripsPosBase: TIERulerPosBase read fGripsPosBase write fGripsPosBase;
property Font: TFont read GetFont;
property SnapGrips: TIERulerSnapping read fSnapGrips write SetSnapGrips default iesnNone;
property ConstrainGrips: Boolean read fConstrainGrips write SetConstrainGrips default True;
property AlignToImage: Boolean read fAlignToImage write SetAlignToImage default False;
property Units: TIERulerUnits read fUnits write SetUnits default ieruPixels;
property HorzHeight: Integer read fHorzHeight write SetHorzHeight default 40;
property VertWidth: Integer read fVertWidth write SetVertWidth default 40;
// EVENTS
property OnRulerGripPosChange: TRulerGripPosChangeEvent read GetOnRulerPosChange write SetOnRulerPosChange;
property OnRulerGripClick: TRulerGripClickEvent read GetOnRulerGripClick write SetOnRulerGripClick;
property OnRulerGripDblClick: TRulerGripClickEvent read GetOnRulerGripDblClick write SetOnRulerGripDblClick;
property OnRulerClick: TRulerClickEvent read GetOnRulerClick write SetOnRulerClick;
// Need to handle the following in objects that use this class
procedure Update(DoInvalidate: Boolean = True);
procedure Paint(Canvas: TCanvas);
function HandleMouseMove(Shift: TShiftState; X, Y: Integer): Boolean;
procedure HandleMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure HandleMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure HandleSpecialKey(CharCode: Word; Shift: TShiftState);
// Internal Helper properties
property HorzRulerRect: TRect read GetHorzRulerRect;
property VertRulerRect: TRect read GetVertRulerRect;
function RulerAreaLeft: Integer;
function RulerAreaRight: Integer;
function RulerAreaTop: Integer;
function RulerAreaBottom: Integer;
procedure ScrollToHorzGrip(g: Integer);
procedure ScrollToVertGrip(g: Integer);
end;
implementation
uses
iexThemes, imageenproc, hyieutils, hyiedefs, imageenview, RulerBox, Forms;
{$R-}
type
TRUGrip = record
Pos: double; // position
Color: TColor; // color
Kind: TGripKind; // type
Min: double; // min position
Max: double; // max position
Default: Boolean; // If false, then a custom color and kind have been set
end;
PRUGrip = ^TRUGrip;
const
// Number of points for each grip type
NumLinesGKind: array[gkTriangle..gkLine] of integer = (
3, // gkTriangle
3, // gkLeftTriangle
3, // gkRightTriangle
7, // gkArrow
5, // gkArrow2
2 // gkLine
);
Ruler_To_Text_Spacing = 3; // Distance between ruler and labels
NON_VIZ = -10000; // Grip is not shown
/////////////////////////////////////////////////////////////////////////////////////////
// //
// TIERULER //
// //
/////////////////////////////////////////////////////////////////////////////////////////
constructor TIERuler.Create(Owner: TControl);
begin
inherited Create();
fOwner := Owner;
IEGDIPLoadLibrary();
fFont := TFont.Create;
fGripIndexOffset := 0;
if fOwner is TImageEnVIew then
fGripIndexOffset := 1
else
if fOwner is TRulerBox then
fFont.Assign( TRulerBox( fOwner ).Font );
fFont.OnChange := FontChange;
fLockUpdateCount := 0;
fRulerDir := rdHorizontal;
fOffsetX := 0;
fOffsetY := 0;
fInverted := false;
fHexLabels := false;
fGripsDir := gdUp;
fBackground := clBtnFace;
fGripBaseDim := 12;
fShowRuler := true;
fViewPos := 0;
fDPU := 1;
fFrequency := 10;
fLabelFreq := 40;
fRulerColor := clBtnFace;
fViewMin := 0;
fViewMax := 0;
fMaxGripHeight := 15;
fOnRulerGripPosChange := nil;
fOnRulerGripClick := nil;
fOnRulerGripDblClick := nil;
fOnRulerClick := nil;
fFitInView := false;
fBitmap := TBitmap.create;
fBitmap.PixelFormat := pf24bit;
fBitmap.Width := fOwner.Width - fOffsetX;
fBitmap.Height := fOwner.Height - fOffsetY;
fGrips := TList.Create;
fSelGrip := -1;
fScrollRate := 1.0;
fLabelPrecision := 3;
fMinLabelSpacing := 30;
fGripPenColor := clWindowFrame;
fGripKindDefault := gkTriangle;
fGripColorDefault := clBtnFace;
SetGripsCount(1);
Update();
end;
destructor TIERuler.Destroy;
var
i: integer;
begin
FreeAndNil( fBitmap );
FreeAndNil( fFont );
for i := 0 to fGrips.Count-1 do
dispose(fGrips[i]);
FreeAndNil(fGrips);
IEGDIPUnLoadLibrary();
inherited;
end;
procedure TIERuler.DrawToCanvas(Canvas: TCanvas; X, Y: Integer);
begin
Canvas.Draw( X + fOffsetX, Y + fOffsetY, fBitmap);
end;
procedure TIERuler.UpdateSize(Width, Height: integer);
begin
fBitmap.Width := imax( 0, Width - fOffsetX );
fBitmap.Height := imax( 0, Height - fOffsetY );
Update();
end;
procedure TIERuler.SetBackground(bk: TColor);
begin
fBackground := bk;
Update();
end;
function TIERuler.GetGripsCount: integer;
begin
result := fGrips.Count;
end;
procedure TIERuler.SetGripsCount(v: integer);
var
ex, q: integer;
begin
ex := fGrips.Count;
if v <> ex then
begin
if v < ex then
// free
for q := ex-1 downto v do
dispose(fGrips[q]);
fGrips.Count := v;
// init
for q := ex to v - 1 do
begin
fGrips[q] := new(PRUGrip);
// defaults
PRUGrip(fGrips[q])^.Pos := 0;
PRUGrip(fGrips[q])^.Color := GetThemeColor( ietpRulerGripFill, fGripColorDefault );
PRUGrip(fGrips[q])^.Kind := fGripKindDefault;
PRUGrip(fGrips[q])^.Min := fViewMin;
PRUGrip(fGrips[q])^.Max := fViewMax;
PRUGrip(fGrips[q])^.Default := True;
end;
Update();
end;
end;
procedure TIERuler.SetGripPenColor(const Value: TColor);
begin
fGripPenColor := Value;
Update();
end;
function TIERuler.GetGripsPos(i: integer): double;
begin
if i < fGrips.Count then
result := PRUGrip(fGrips[i])^.Pos
else
result := 0;
end;
procedure TIERuler.SetGripsPos(i: integer; p: double);
begin
if i < fGrips.Count then
begin
PRUGrip(fGrips[i])^.Pos := p;
AdjustGripLimits(i);
if assigned( fOnRulerGripPosChange ) and
( i >= fGripIndexOffset ) then
fOnRulerGripPosChange( self, fRulerDir, i - fGripIndexOffset, PRUGrip(fGrips[i])^.Pos );
UpdateEx( False, True );
end;
end;
function TIERuler.GetGripsColor(i: integer): TColor;
begin
if i < fGrips.Count then
result := PRUGrip(fGrips[i])^.Color
else
result := 0;
end;
procedure TIERuler.SetGripsColor(i: integer; p: TColor);
begin
if i < fGrips.Count then
begin
PRUGrip(fGrips[i])^.Color := p;
PRUGrip(fGrips[i])^.Default := False;
Update();
end;
end;
procedure TIERuler.SetGripColorDefault(const Value: TColor);
var
i: Integer;
begin
fGripColorDefault := Value;
for i := 0 to fGrips.Count - 1 do
if PRUGrip( fGrips[ i ])^.Default then
PRUGrip( fGrips[ i ])^.Color := Value;
Update();
end;
procedure TIERuler.SetGripBaseDim(v: integer);
begin
fGripBaseDim := v;
Update();
end;
function TIERuler.GetGripsKind(i: integer): TGripKind;
begin
result := gkTriangle; // default
if i < fGrips.Count then
result := PRUGrip(fGrips[i])^.Kind;
end;
procedure TIERuler.SetGripsKind(i: integer; v: TGripKind);
begin
if i < fGrips.Count then
begin
PRUGrip(fGrips[i])^.Kind := v;
PRUGrip(fGrips[i])^.Default := False;
Update();
end;
end;
procedure TIERuler.SetGripKindDefault(const Value: TGripKind);
var
i: Integer;
begin
fGripKindDefault := Value;
for i := 0 to fGrips.Count - 1 do
if PRUGrip( fGrips[ i ])^.Default then
PRUGrip( fGrips[ i ])^.Kind := Value;
Update();
end;
// return -1 = none
function TIERuler.GetClickedGrip(x, y: integer): integer;
var
q: integer;
rc: TRect;
begin
result := -1;
for q := fGrips.Count - 1 downto 0 do
begin
GetGripRect(q, rc);
if PtInRect(rc, Point(x, y)) then
begin
result := q;
break;
end;
end;
end;
// returns the rectangle where the grip "gn" is contained.
// Right and bottom borders are incremented by 1 to make them compatible with PtInRect.
procedure TIERuler.GetGripRect(gn: integer; var rc: TRect);
var
poly: TIEPolyg;
q: integer;
begin
if GripsKind[ gn ] = gkNone then
begin
rc := Rect( 0, 0, -1, -1 );
exit;
end;
GetGripPoly(gn, poly);
rc.TopLeft := poly[0];
rc.BottomRight := poly[0];
for q := 1 to NumLinesGKind[GripsKind[gn]] - 1 do
begin
if poly[q].X < rc.Left then
rc.Left := poly[q].X;
if poly[q].X > rc.Right then
rc.Right := poly[q].X;
if poly[q].Y < rc.Top then
rc.Top := poly[q].Y;
if poly[q].Y > rc.Bottom then
rc.Bottom := poly[q].Y;
end;
inc(rc.Bottom);
inc(rc.Right);
end;
procedure TIERuler.SetGripsDir(v: TGripsDir);
begin
fGripsDir := v;
Update();
end;
procedure TIERuler.SetShowBorder(const Value: boolean);
begin
fShowBorder := Value;
Update();
end;
procedure TIERuler.SetShowRuler(v: boolean);
begin
fShowRuler := v;
Update();
end;
// return height of ruler+text
function TIERuler.GetRulerHeight: integer;
const
Min_Tick_Size = 3;
Min_Grip_Height = 3;
var
minHeight, availHeight: Integer;
begin
result := 0;
if fShowRuler = False then
exit;
// New method
if fOwner is TImageEnView then
begin
if fRulerDir = rdHorizontal then
availHeight := fBitmap.Height
else
availHeight := fBitmap.Width;
minHeight := abs( fFont.Height ) + Ruler_To_Text_Spacing + Min_Tick_Size;
result := availHeight - fMaxGripHeight;
if result < minHeight then
result := minHeight;
if Result + Min_Grip_Height > availHeight then
Result := availHeight - Min_Grip_Height;
end
else
begin
// Legacy method (TRulerBox)
if fRulerDir = rdHorizontal then
result := trunc( abs( fFont.Height ) * 1.5 ) + Ruler_To_Text_Spacing
else
result := fBitmap.Width - fMaxGripHeight;
end;
end;
procedure TIERuler.Update();
begin
UpdateEx( True, True );
end;
procedure TIERuler.UpdateEx(RepaintAll, DoInvalidate : Boolean);
begin
if fLockUpdateCount > 0 then
exit
else
if ( fOwner is TImageEnView ) and
( TImageEnView( fOwner ).LockUpdateCount > 0 ) then
exit
else
if ( fOwner is TImageEnView ) and
(( fRulerDir in TImageEnView( fOwner ).ShowRulers ) = False ) then
exit;
if fFitinView then
begin
if (fViewMax - fViewMin <> 0) then
fDPU := (fBitmap.Width) / (fViewMax - fViewMin);
AdjustViewLimits;
RepaintAll := True;
end;
RepaintGrips;
if RepaintAll then
RepaintRuler;
if fShowBorder then
RepaintBorder;
if DoInvalidate then
fOwner.invalidate;
end;
procedure TIERuler.SetViewPos(v: double);
begin
fViewPos := v;
AdjustViewLimits;
Update();
end;
procedure TIERuler.SetFrequency(v: double);
begin
fFrequency := v;
Update();
end;
procedure TIERuler.SetLabelFreq(v: double);
begin
fLabelFreq := v;
Update();
end;
// returns X position (in pixels) of grip "gn"
function TIERuler.GetXGripPos(gn: integer): integer;
begin
result := round(fDPU * (GripsPos[gn] - fViewPos));
if fInverted then
begin
if fRulerDir = rdHorizontal then
result := fBitmap.Width - result
else
result := fBitmap.Height - result;
end;
end;
procedure TIERuler.SetRulerColor(v: TColor);
begin
fRulerColor := v;
Update();
end;
procedure TIERuler.SetRulerDir(v: TRulerDir);
begin
fRulerDir := v;
Update();
end;
// returns coordinates of points making the grip
procedure TIERuler.GetGripPoly(gn: integer; var poly: TIEPolyg);
var
w, h, b: integer;
borderSize: integer;
begin
borderSize := 0;
if fShowBorder and ( GripsKind[gn] <> gkLine ) then
borderSize := 1;
b := 0;
h := 0;
if csDesigning in fOwner.ComponentState then
w := (fGripBaseDim + 5) * gn
else
w := GetXGripPos(gn);
if fGripsDir = gdUp then
begin
if fRulerDir = rdHorizontal then
begin
h := fBitmap.Height - 2 - borderSize;
b := 0;
end
else
begin
h := fBitmap.Width - 2 - borderSize;
b := 0;
end;
if fShowRuler then
inc(b, GetRulerHeight);
end
else
if fGripsDir = gdDown then
begin
if fRulerDir = rdHorizontal then
begin
b := fBitmap.Height - 1;
h := 1 + borderSize;
end
else
begin
b := fBitmap.Width - 1;
h := 1 + borderSize;
end;
if fShowRuler then
dec(b, GetRulerHeight);
end;
case GripsKind[gn] of
gkTriangle:
begin
poly[0].x := w - (fGripBaseDim div 2);
poly[0].y := h;
poly[1].x := w + (fGripBaseDim div 2);
poly[1].y := h;
poly[2].x := w;
poly[2].y := b;
end;
gkLeftTriangle:
begin
poly[0].x := w - (fGripBaseDim div 2);
poly[0].y := h;
poly[1].x := w;
poly[1].y := h;
poly[2].x := w;
poly[2].y := b;
end;
gkRightTriangle:
begin
poly[0].x := w;
poly[0].y := h;
poly[1].x := w + (fGripBaseDim div 2);
poly[1].y := h;
poly[2].x := w;
poly[2].y := b;
end;
gkArrow:
begin
poly[0].x := w - (fGripBaseDim div 4);
poly[0].y := h;
poly[1].x := w + (fGripBaseDim div 4);
poly[1].y := poly[0].y;
poly[2].x := poly[1].x;
if fGripsDir = gdUp then
poly[2].y := b + ((h - b) div 2)
else
poly[2].y := h + ((b - h) div 2);
poly[3].x := w + (fGripBaseDim div 2);
poly[3].y := poly[2].y;
poly[4].x := w;
poly[4].y := b;
poly[5].x := w - (fGripBaseDim div 2);
poly[5].y := poly[2].y;
poly[6].x := poly[0].x;
poly[6].y := poly[2].y;
end;
gkArrow2:
begin
poly[0].x := w - (fGripBaseDim div 2);
poly[0].y := h;
poly[1].x := w + (fGripBaseDim div 2);
poly[1].y := poly[0].y;
poly[2].x := poly[1].x;
if fGripsDir = gdUp then
poly[2].y := b + (h - b) div 2
else
poly[2].y := h + (b - h) div 2;
poly[3].x := w;
poly[3].y := b;
poly[4].x := poly[0].x;
poly[4].y := poly[2].y;
end;
gkLine:
begin
poly[0].x := w;
poly[0].y := h;
poly[1].x := w;
poly[1].y := b;
end;
end;
if fRulerDir = rdVertical then
for w := 0 to NumLinesGKind[GripsKind[gn]] - 1 do
iswap(poly[w].x, poly[w].y);
end;
procedure TIERuler.RepaintGrips;
var
q, rh: integer;
poly: TIEPolyg;
iec: TIECanvas;
begin
iec := TIECanvas.Create( fBitmap.Canvas, true, true);
iec.Brush.Color := GetThemeColor( ietpRulerBackground, fBackground );
rh := GetRulerHeight;
if fRulerDir = rdHorizontal then
begin
if fGripsDir = gdUp then
iec.Fillrect(rect(0, rh, fBitmap.Width, fBitmap.Height))
else
if fgripsDir = gdDown then
iec.FillRect(rect(0, 0, fBitmap.Width, fBitmap.Height - rh));
end
else
begin
if fGripsDir = gdUp then
iec.FillRect(rect(rh, 0, fBitmap.Width, fBitmap.Height))
else
if fgripsDir = gdDown then
iec.FillRect(rect(0, 0, fBitmap.Width - rh, fBitmap.Height));
end;
for q := 0 to fGrips.Count - 1 do
if ( GripsKind[ q ] <> gkNone ) and ( GripsPos[ q ] <> NON_VIZ ) then
begin
GetGripPoly(q, poly);
// paint grip
iec.Brush.Color := GripsColor[q];
iec.Pen.Color := GetThemeColor( ietpRulerGripBorder, fGripPenColor );
iec.Polygon(slice(poly, NumLinesGKind[GripsKind[q]]));
end;
iec.Free;
end;
// adjusts limits of specified grip (looking at Max and Min)
procedure TIERuler.AdjustGripLimits(gn: integer);
begin
if GripsMin[gn] < GripsMax[gn] then
begin
if GripsPos[gn] < GripsMin[gn] then
GripsPos[gn] := GripsMin[gn]
else
if GripsPos[gn] > GripsMax[gn] then
GripsPos[gn] := GripsMax[gn];
end;
end;
// adjusts limits of fViewPos (looking at fViewMin and fViewMax)
procedure TIERuler.AdjustViewLimits;
var
wiu: Double;
begin
if ( fViewMin < fViewMax ) and ( fBitmap.Width > 0 ) then
begin
// return horizontal size in Units
wiu := fBitmap.Width / fDPU;
if fViewPos < fViewMin then
fViewPos := fViewMin
else
if fViewPos > (fViewMax - wiu) then
fViewpos := dmax(0, fViewMax - wiu);
end;
end;
procedure TIERuler.HandleMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
inherited;
{$IFDEF IEDEBUG}
OutputDebugStringA( 'Mouse Down' );
{$ENDIF}
dec(X, fOffsetX);
dec(Y, fOffsetY);
if (Button = mbLeft) then
begin
fSelGrip := GetClickedGrip(x, y);
fMX1 := X;
fMY1 := Y;
if fSelGrip >= 0 then
begin
if (ssDouble in Shift) and assigned(fOnRulerGripDblClick) and
( fSelGrip >= fGripIndexOffset ) then
fOnRulerGripDblClick( fOwner, fRulerDir, fSelGrip - fGripIndexOffset, PRUGrip( fGrips[ fSelGrip ])^.Pos );
fSelGripSt := GetXGripPos( fSelGrip );
end
else
begin
if assigned(fOnRulerClick) then
fOnRulerClick( fOwner, fRulerDir, X / fDPU + fViewPos);
end;
end;
end;
procedure TIERuler.HandleMouseMove(Shift: TShiftState; X, Y: Integer);
begin
HandleMouseMoveEx( Shift, X, Y, nil );
end;
procedure TIERuler.HandleMouseMoveEx(Shift: TShiftState; X, Y: Integer; SetGripCallBack: TRulerSetGripPosEvent);
{}
procedure _DoScroll_IEView(Dir: Integer);
begin
case Dir of
VK_LEFT:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt - fMX1 ) / fDPU + fViewPos - (fScrollRate / fDPU);
TImageEnView(fOwner).ViewX := Round( TImageEnView(fOwner).ViewX - (fScrollRate / fDPU));
end;
VK_RIGHT:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt + fBitmap.Width - 1 - fMX1 ) / fDPU + fViewPos + (fScrollRate / fDPU);
TImageEnView(fOwner).ViewX := Round( TImageEnView(fOwner).ViewX + (fScrollRate / fDPU));
end;
VK_UP:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt - fMY1 ) / fDPU + fViewPos - (fScrollRate / fDPU);
if fOwner is TImageEnView then
TImageEnView(fOwner).ViewY := Round( TImageEnView(fOwner).ViewY - (fScrollRate / fDPU));
end;
VK_DOWN:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt + fBitmap.Height- 1 - fMY1 ) / fDPU + fViewPos + (fScrollRate / fDPU);
TImageEnView(fOwner).ViewY := Round( TImageEnView(fOwner).ViewY + (fScrollRate / fDPU));
end;
end;
AdjustGripLimits( fSelGrip );
AdjustViewLimits;
if assigned(fOnRulerGripPosChange) and
( fSelGrip >= fGripIndexOffset ) then
fOnRulerGripPosChange( fOwner, fRulerDir, fSelGrip - fGripIndexOffset, PRUGrip( fGrips[ fSelGrip ])^.Pos );
end;
{}
function _DoScroll_RB(Dir: Integer): integer;
var
p: TPoint;
begin
GetCursorPos(p);
p := fOwner.ScreenToClient(p);
case Dir of
VK_LEFT:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt - fMX1 ) / fDPU + fViewPos - (fScrollRate / fDPU);
fViewPos := fViewPos - (fScrollRate / fDPU);
end;
VK_RIGHT:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt + fBitmap.Width - 1 - fMX1 ) / fDPU + fViewPos + (fScrollRate / fDPU);
fViewPos := fViewPos + (fScrollRate / fDPU);
end;
VK_UP:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt - fMY1 ) / fDPU + fViewPos - (fScrollRate / fDPU);
fViewPos := fViewPos - (fScrollRate / fDPU);
end;
VK_DOWN:
begin
PRUGrip(fGrips[ fSelGrip ])^.Pos := ( fSelGripSt + fBitmap.Height- 1 - fMY1 ) / fDPU + fViewPos + (fScrollRate / fDPU);
fViewPos := fViewPos + (fScrollRate / fDPU);
end;
end;
AdjustGripLimits( fSelGrip );
AdjustViewLimits;
RepaintGrips;
RepaintRuler;
fOwner.Invalidate();
if assigned(fOnRulerGripPosChange) and
( fSelGrip >= fGripIndexOffset ) then
fOnRulerGripPosChange( fOwner, fRulerDir, fSelGrip - fGripIndexOffset, PRUGrip( fGrips[ fSelGrip ])^.Pos );
if Dir in [ VK_LEFT, VK_RIGHT ] then
result := p.X
else
result := p.Y;
end;
{}
function _CheckConstraints(v: Double) : Double;
begin
Result := v;
if assigned( SetGripCallBack ) then
SetGripCallBack( Self, Result );
end;
{}
function _CheckInverted(Dir: Integer) : Integer;
begin
Result := Dir;
if fInverted then
case Dir of
VK_LEFT : Result := VK_RIGHT;
VK_RIGHT : Result := VK_LEFT ;
VK_UP : Result := VK_DOWN ;
VK_DOWN : Result := VK_UP ;
end;
end;
{}
var
isMouseCapture: Boolean;
begin
inherited;
//
dec(X, fOffsetX);
dec(Y, fOffsetY);
isMouseCapture := False;
if fOwner is TRulerBox then
isMouseCapture := TRulerBox( fOwner ).MouseCapture
else
if fOwner is TImageEnView then
isMouseCapture := TImageEnView( fOwner ).MouseCapture;
if isMouseCapture then
if (fSelGrip >= 0) then
begin
if fRulerDir = rdHorizontal then
begin
if X < 0 then
begin
// Scroll Left
if fOwner is TImageEnView then
_DoScroll_IEView( _CheckInverted( VK_LEFT ))
else
while ( _DoScroll_RB( _CheckInverted( VK_LEFT )) < 0) and (GetAsyncKeyState(VK_LBUTTON) <> 0) do
Application.ProcessMessages
end
else
if X >= fBitmap.Width then
begin
// Scroll Right
if fOwner is TImageEnView then
_DoScroll_IEView( _CheckInverted( VK_RIGHT ))
else
while ( _DoScroll_RB( _CheckInverted( VK_RIGHT )) >= fBitmap.Width) and (GetAsyncKeyState(VK_LBUTTON) <> 0) do
Application.ProcessMessages
end
else
begin
// Move Horz Grip
if fInverted then
SetGripsPos( fSelGrip, _CheckConstraints(( fSelGripSt + (fBitmap.Width-X) - fMX1) / fDPU + fViewPos ))
else
SetGripsPos( fSelGrip, _CheckConstraints(( fSelGripSt + X - fMX1) / fDPU + fViewPos ));
fOwner.Invalidate();
end;
end
else
begin
if Y < 0 then
begin
// Scroll Up
if fOwner is TImageEnView then
_DoScroll_IEView( _CheckInverted( VK_UP ))
else
while ( _DoScroll_RB( _CheckInverted( VK_UP )) < 0) and (GetAsyncKeyState(VK_LBUTTON) <> 0) do
Application.ProcessMessages
end
else
if Y >= fBitmap.Height then
begin
// Scroll Down
if fOwner is TImageEnView then
_DoScroll_IEView( _CheckInverted( VK_DOWN ))
else
while ( _DoScroll_RB( _CheckInverted( VK_DOWN )) >= fBitmap.height) and (GetAsyncKeyState(VK_LBUTTON) <> 0) do
Application.ProcessMessages
end
else
begin
// Move Vert Grip
if fInverted then
SetGripsPos( fSelGrip, _CheckConstraints(( fSelGripSt + (fBitmap.Height-Y) - fMY1) / fDPU + fViewPos ))
else
SetGripsPos( fSelGrip, _CheckConstraints(( fSelGripSt + Y - fMY1) / fDPU + fViewPos ));
fOwner.Invalidate();
end;
end
end;
end;
// fMouseSel 0=none 1=capture on sat/val 2=capture on hue
procedure TIERuler.HandleMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
{$IFDEF IEDEBUG}
OutputDebugStringA( 'Mouse Up' );
{$ENDIF}
dec(X, fOffsetX);
dec(Y, fOffsetY);
if fSelGrip >= 0 then
begin
if (fMX1 = X) and (fMY1 = Y) and assigned(fOnRulerGripClick) and
( fSelGrip >= fGripIndexOffset ) then
fOnRulerGripClick( fOwner, fRulerDir, fSelGrip - fGripIndexOffset, PRUGrip( fGrips[ fSelGrip ])^.Pos );
end;
end;
function TIERuler.GetGripsMax(i: integer): double;
begin
if i < fGrips.Count then
result := PRUGrip(fGrips[i])^.Max
else
result := 0;
end;
procedure TIERuler.SetGripsMax(i: integer; v: double);
var
q: integer;
begin
if (i < fGrips.Count) then
begin
PRUGrip(fGrips[i])^.Max := v;
for q := 0 to fGrips.Count - 1 do
AdjustGripLimits(q);
Update();
end;
end;
function TIERuler.GetGripsMin(i: integer): double;
begin
if i < fGrips.Count then
result := PRUGrip(fGrips[i])^.Min
else
result := 0;
end;
procedure TIERuler.SetGripsMin(i: integer; v: double);
var
q: integer;
begin
if (i < fGrips.Count) then
begin
PRUGrip(fGrips[i])^.Min := v;
for q := 0 to fGrips.Count - 1 do
AdjustGripLimits(q);
Update();
end;
end;
procedure TIERuler.SetViewMin(v: double);
var
q: integer;
begin
fViewMin := v;
AdjustViewLimits;
for q := 0 to fGrips.Count - 1 do
PRUGrip(fGrips[q])^.Min := fViewMin;
Update();
end;
procedure TIERuler.SetViewMax(v: double);
var
q: integer;
begin
fViewMax := v;
AdjustViewLimits;
for q := 0 to fGrips.Count - 1 do
PRUGrip(fGrips[q])^.Max := fViewMax;
Update();
end;
procedure TIERuler.RepaintBorder;
{}
procedure _DrawBorder(x1, y1, x2, y2 : Integer);
begin
fBitmap.Canvas.MoveTo( x1, y1 );
fBitmap.Canvas.LineTo( x2, y2 );
end;
{}
begin
fBitmap.Canvas.Pen.Color := GetThemeColor( ietpRulerBorder, clBtnShadow );
if fRulerDir = rdHorizontal then
begin
if fGripsDir = gdDown then
_DrawBorder( 0, 0, fBitmap.Width, 0 )
else
_DrawBorder( 0, fBitmap.Height - 1, fBitmap.Width, fBitmap.Height - 1 );
end
else
begin
if fGripsDir = gdDown then
_DrawBorder( 0, 0, 0, fBitmap.Height )
else
_DrawBorder( fBitmap.Width - 1, 0, fBitmap.Width - 1, fBitmap.Height );
end;
end;
// repaint ruler+text
procedure TIERuler.RepaintRuler;
var
LogFont: TLogFontA;
SaveFont: TFont;
rl: integer; // ruler height
bigTickFreq : Double; // Local value of fLabelFreq
littleTickFreq: Double; // Local value of fFrequency
bigTickSpacing: Integer; // Pixels between big ticks
fontColor: TColor;
{}
function _FloatToLabel(v: double) : string;
var
lb1: string;
e: integer;
begin
if fHexLabels then
begin
lb1 := IntToHex(trunc(abs( v )), 6);
// remove starting zeros
Result := '0';
for e := 1 to length(lb1) do
if lb1[e] <> '0' then
begin
Result := Copy(lb1, e, length(lb1));
break;
end;
if v < 0 then
Result := '-' + Result;
end
else
Result := IEFloatToFormatString( v, fLabelPrecision, True );
end;
{}
procedure _DrawHorzTicks(TickFrequency: Double; TickScale: Integer; DrawLabel: Boolean);
var
q, w: integer;
z, v: double; // pos in unit
x: integer; // pos in pixel
xx: integer; // Draw pos
lb: string;
begin
w := trunc((fBitmap.Width / fDPU) / TickFrequency); // number of lines
for q := 0 to w + 1 do
begin
v := ((fViewPos / TickFrequency) - trunc(fViewPos / TickFrequency)) * TickFrequency;
z := q * TickFrequency + fViewPos - v;
x := round((z - fViewPos) * fDPU);
if fInverted then
x := fBitmap.Width - x;
if fGripsDir = gdDown then
begin // DOWN
fBitmap.Canvas.MoveTo( x, fBitmap.Height - rl );
fBitmap.Canvas.LineTo( x, fBitmap.Height - rl + ( rl div TickScale ) - 1 );
end
else
begin // UP
fBitmap.Canvas.MoveTo( x, rl - 1 );
fBitmap.Canvas.LineTo( x, rl - ( rl div TickScale ) + 1 );
end;
if DrawLabel then
begin
lb := _FloatToLabel( z );
xx := x - (fBitmap.Canvas.TextWidth(lb) div 2);
if xx <= 0 then
begin { Don't draw half a zero } end
else
if fGripsDir = gdDown then
fBitmap.Canvas.TextOut(xx, fBitmap.Height - fBitmap.Canvas.TextHeight( lb ), lb)
else
fBitmap.Canvas.TextOut(xx, 0, lb);
end;
end;
end;
{}
procedure _DrawVertTicks(TickFrequency: Double; TickScale: Integer; DrawLabel: Boolean);
var
w, q: Integer;
z, v: double; // pos in unit
y: integer; // pos in pixel
yy: integer; // Draw pos
lb: string;
tw: Integer;
begin
w := trunc((fBitmap.Height / fDPU) / TickFrequency); // number of rows
for q := 0 to w + 1 do
begin
v := ((fViewPos / TickFrequency) - trunc(fViewPos / TickFrequency)) * TickFrequency;
z := q * TickFrequency + fViewPos - v;
y := round((z - fViewPos) * fDPU);
if fInverted then
y := fBitmap.Height - y;
if fGripsDir = gdDown then
begin // DOWN
fBitmap.Canvas.MoveTo( fBitmap.Width - rl, y );
fBitmap.Canvas.LineTo( fBitmap.Width - rl + ( rl div TickScale ), y );
end
else
begin // UP
fBitmap.Canvas.MoveTo( rl - 1, y );
fBitmap.Canvas.LineTo( rl - ( rl div TickScale ) - 1, y );
end;
if DrawLabel then
begin
lb := _FloatToLabel( z );
tw := fBitmap.Canvas.TextWidth( lb );
if fGripsDir = gdDown then
begin // DOWN
yy := y - ( tw div 2 );
if yy > 0 then // Don't draw half a zero
fBitmap.Canvas.TextOut(fBitmap.Width, yy, lb);
end
else
begin // UP
yy := y + ( tw div 2 );
if yy - tw > 0 then // Don't draw half a zero
fBitmap.Canvas.TextOut(0, yy, lb);
end;
end;
end;
end;
{}
begin
if not fShowRuler then
exit;
fBitmap.Canvas.Brush.Color := GetThemeColor( ietpRuler, fRulerColor );
rl := GetRulerHeight;
if fRulerDir = rdHorizontal then
begin
if fGripsDir = gdDown then
fBitmap.Canvas.Fillrect(Rect(0, fBitmap.Height - rl, fBitmap.Width, fBitmap.Height))
else
fBitmap.Canvas.Fillrect(Rect(0, 0, fBitmap.Width, rl));
end
else
begin
if fGripsDir = gdDown then
fBitmap.Canvas.Fillrect(Rect(fBitmap.Width - rl, 0, fBitmap.Width, fBitmap.Height))
else
fBitmap.Canvas.Fillrect(Rect(0, 0, rl, fBitmap.Height));
end;
// paint
fBitmap.Canvas.Font := fFont;
fontColor := GetThemeColor( ietpRulerText, fFont.Color );
fBitmap.Canvas.Font.Color := fontColor;
fBitmap.Canvas.Pen.Color := fontColor;
bigTickFreq := fLabelFreq;
littleTickFreq := fFrequency;
// Scale spacing
bigTickSpacing := imax( 1, Round( fDPU * bigTickFreq ));
if ( fMinLabelSpacing > 0 ) then
while bigTickSpacing < fMinLabelSpacing do
begin
bigTickFreq := 2 * bigTickFreq ;
littleTickFreq := 2 * littleTickFreq;
bigTickSpacing := imax( 1, Round( fDPU * bigTickFreq ));
end;
if fRulerDir = rdVertical then
begin
// VERTICAL
// pepare vertical font
SaveFont := TFont.Create;
SaveFont.assign(fBitmap.Canvas.Font);
GetObject(SaveFont.Handle, sizeof(TLogFontA), @LogFont);
if fGripsDir = gdDown then
LogFont.lfEscapement := -900 // -90 degrees
else
LogFont.lfEscapement := 900; // 90 degrees
LogFont.lfPitchAndFamily := FIXED_PITCH or FF_DONTCARE;
fBitmap.Canvas.Font.Handle := CreateFontIndirectA(LogFont);
// paint long ticks and text
_DrawVertTicks( bigTickFreq, 2, True );
// Paint little ticks
_DrawVertTicks( littleTickFreq, 4, False );
// free font
fBitmap.Canvas.Font.Assign(SaveFont);
FreeAndNil(SaveFont);
end
else
begin
// HORIZONTAL
// Paint long ticks and text
_DrawHorzTicks( bigTickFreq, 2, True );
// Paint little ticks
_DrawHorzTicks( littleTickFreq, 4, False );
end;
end;
procedure TIERuler.SetFitInView(v: boolean);
begin
fFitInView := v;
Update();
end;
procedure TIERuler.SetDPU(v: double);
begin
if (csDesigning in fOwner.ComponentState) and fFitInView then
exit;
fDPU := v;
Update();
end;
procedure TIERuler.SetHexLabels(v: boolean);
begin
fHexLabels := v;
Update();
end;
procedure TIERuler.SetInverted(v: boolean);
begin
fInverted := v;
Update();
end;
procedure TIERuler.SetOffsetX(v: integer);
begin
fOffsetX := v;
fBitmap.Width := fOwner.Width - fOffsetX;
Update();
end;
procedure TIERuler.SetOffsetY(v: integer);
begin
fOffsetY := v;
fBitmap.Height := fOwner.Height - fOffsetY;
Update();
end;
procedure TIERuler.SetLabelPrecision(v: integer);
begin
fLabelPrecision := v;
Update();
end;
procedure TIERuler.SetMinLabelSpacing(v: integer);
begin
fMinLabelSpacing := v;
Update();
end;
procedure TIERuler.LockUpdate();
begin
Inc( fLockUpdateCount );
end;
procedure TIERuler.UnlockUpdate(RepaintAll: Boolean = True; DoInvalidate: Boolean = True);
begin
Dec( fLockUpdateCount );
if fLockUpdateCount < 1 then
UpdateEx( RepaintAll, DoInvalidate );
end;
procedure TIERuler.FontChange(Sender: TObject);
begin
Update();
end;
/////////////////////////////////////////////////////////////////////////////////////////
// //
// TIEViewRulerParams //
// //
/////////////////////////////////////////////////////////////////////////////////////////
constructor TIEViewRulerParams.Create(Owner: TControl);
begin
if not ( Owner is TImageEnView ) then
raise EIEException.create( 'Only TImageEnView supported' );
fOwner := Owner;
fHorzRuler := TIERuler.Create( Owner );
fHorzRuler.RulerDir := rdHorizontal;
fHorzRuler.LabelPrecision := 2;
fHorzRuler.RulerColor := clBtnShadow;
fHorzRuler.ShowBorder := True;
fHorzRuler.GripColorDefault := cl3DLight;
fVertRuler := TIERuler.Create( Owner );
fVertRuler.RulerDir := rdVertical;
fVertRuler.LabelPrecision := 2;
fVertRuler.RulerColor := clBtnShadow;
fVertRuler.ShowBorder := True;
fVertRuler.GripColorDefault := clWindow;
fSnapGrips := iesnNone;
fConstrainGrips := True;
fAlignToImage := False;
fUnits := ieruPixels;
fWasUnits := ieruPixels;
fHorzPos := gdUp;
fVertPos := gdLeft;
fHorzHeight := 40;
fVertWidth := 40;
fLastMouseMoveX := -99;
fLastMouseMoveY := -99;
fGripsPosBase := ierbBitmap;
fHorzRuler.GripsCount := 1;
fVertRuler.GripsCount := 1;
fHorzRuler.GripsKind[ 0 ] := gkLine;
fVertRuler.GripsKind[ 0 ] := gkLine;
fHorzRuler.GripsPos[ 0 ] := NON_VIZ;
fVertRuler.GripsPos[ 0 ] := NON_VIZ;
Font.OnChange := FontChange;
Update( False );
end;
destructor TIEViewRulerParams.Destroy;
begin
FreeAndNil( fHorzRuler );
FreeAndNil( fVertRuler );
inherited;
end;
// Update the ruler positions and sizes when the source TImageEnView changes size or content
procedure TIEViewRulerParams.Update(DoInvalidate: Boolean = True);
var
z: double;
ieDpiX, ieDpiY: Integer;
dpux, dpuy: double;
newHorzPos, newVertPos: double;
hRect, vRect: TRect;
I: Integer;
begin
if not ( HorzRulerVisible or VertRulerVisible ) then
exit;
fHorzRuler.LockUpdate();
fVertRuler.LockUpdate();
try
if fAlignToImage then
begin
// Align ruler to position of the image
fHorzRuler.OffsetX := TImageEnView( fOwner ).OffsetX - RulerAreaLeft;
fVertRuler.OffsetY := TImageEnView( fOwner ).OffsetY - RulerAreaTop;
end
else
begin
// Photoshop style: show negative values in ruler
fHorzRuler.OffsetX := 0;
fVertRuler.OffsetY := 0;
end;
hRect := HorzRulerRect;
fHorzRuler.UpdateSize( hRect.Right - hRect.Left, hRect.Bottom - hRect.Top );
vRect := VertRulerRect;
fVertRuler.UpdateSize( vRect.Right - vRect.Left, vRect.Bottom - vRect.Top );
ieDpiX := TImageEnView( fOwner ).IO.Params.DpiX;
ieDpiY := TImageEnView( fOwner ).IO.Params.DpiY;
if ( ieDpiX < 1 ) or ( ieDpiY < 1 ) then
fUnits := ieruPixels;
case fUnits of
ieruInches :
begin
dpux := ieDpiX;
dpuy := ieDpiY;
end;
ieruMillimeters :
begin
dpux := ieDpiX / CM_per_Inch / 10;
dpuy := ieDpiY / CM_per_Inch / 10;
end;
ieruCentimeters :
begin
dpux := ieDpiX / CM_per_Inch;
dpuy := ieDpiY / CM_per_Inch;
end;
else { ieruPixels }
begin
dpux := 1;
dpuy := 1;
end;
end;
z := TImageEnView( fOwner ).Zoom / 100;
newHorzPos := TImageEnView( fOwner ).ViewX / z / dpux;
newVertPos := TImageEnView( fOwner ).ViewY / z / dpuy;
if fAlignToImage = False then
begin
newHorzPos := newHorzPos - ( TImageEnView( fOwner ).OffsetX - RulerAreaLeft ) / z / dpux;
newVertPos := newVertPos - ( TImageEnView( fOwner ).OffsetY - RulerAreaTop ) / z / dpuy;
end;
fHorzRuler.ViewPos := newHorzPos;
fVertRuler.ViewPos := newVertPos;
if fUnits <> fWasUnits then
begin
// Repositon all grips
for I := 0 to fHorzRuler.GripsCount do
fHorzRuler.GripsPos[ I ] := fHorzRuler.DotPerUnit / ( dpux * z ) * fHorzRuler.GripsPos[ I ];
for I := 0 to fVertRuler.GripsCount do
fVertRuler.GripsPos[ I ] := fVertRuler.DotPerUnit / ( dpuy * z ) * fVertRuler.GripsPos[ I ];
end;
fWasUnits := fUnits;
fHorzRuler.DotPerUnit := z * dpux;
fVertRuler.DotPerUnit := z * dpuy;
finally
fHorzRuler.UnlockUpdate( True, False );
fVertRuler.UnlockUpdate( True, False );
if DoInvalidate and ( fHorzRuler.LockUpdateCount <= 0 ) then
fOwner.Invalidate();
end;
end;
// Draw the rulers to the TImageEnView canvas
procedure TIEViewRulerParams.Paint(Canvas: TCanvas);
begin
{$IFDEF IEDEBUG}
OutputDebugStringW( PWideChar( Format( 'Paint - %d,%d,%d,%d',
[ Canvas.ClipRect.Left,
Canvas.ClipRect.Top,
Canvas.ClipRect.Right,
Canvas.ClipRect.Bottom ])));
{$ENDIF}
if HorzRulerVisible and VertRulerVisible then
begin
Canvas.Brush.Style := bsSolid;
// There will be a corner that needs clearing
if fVertPos = gdLeft then
begin
if fHorzPos = gdUp then
begin
// Top-Left
Canvas.Brush.Color := GetThemeColor( ietpRuler, GetMeasureColor );
Canvas.FillRect( Rect( 0,
0,
fVertWidth,
fHorzHeight ));
Canvas.Brush.Color := GetThemeColor( ietpRulerBackground, GetColor );
Canvas.FillRect( Rect( fHorzRuler.GetRulerHeight,
fVertRuler.GetRulerHeight,
fVertWidth,
fHorzHeight ));
if GetShowBorder() then
Canvas.Pixels[ fVertWidth - 1, fHorzHeight - 1 ] := GetThemeColor( ietpRulerBorder, clBtnShadow );
end
else
begin
// Bottom-Left
Canvas.Brush.Color := GetThemeColor( ietpRuler, GetMeasureColor );
Canvas.FillRect( Rect( 0,
TImageEnView( fOwner ).ClientHeight - fHorzHeight,
fVertWidth,
TImageEnView( fOwner ).ClientHeight ));
Canvas.Brush.Color := GetThemeColor( ietpRulerBackground, GetColor );
Canvas.FillRect( Rect( fHorzRuler.GetRulerHeight,
TImageEnView( fOwner ).ClientHeight - fHorzHeight,
fVertWidth,
TImageEnView( fOwner ).ClientHeight - fVertRuler.GetRulerHeight ));
if GetShowBorder() then
Canvas.Pixels[ fVertWidth - 1, TImageEnView( fOwner ).ClientHeight - fHorzHeight ] := GetThemeColor( ietpRulerBorder, clBtnShadow );
end;
end
else
begin
if fHorzPos = gdUp then
begin
// Top-Right
Canvas.Brush.Color := GetThemeColor( ietpRuler, GetMeasureColor );
Canvas.FillRect( Rect( TImageEnView( fOwner ).ClientWidth - fVertWidth,
0,
TImageEnView( fOwner ).ClientWidth,
fHorzHeight ));
Canvas.Brush.Color := GetThemeColor( ietpRulerBackground, GetColor );
Canvas.FillRect( Rect( TImageEnView( fOwner ).ClientWidth - fVertWidth,
fVertRuler.GetRulerHeight,
TImageEnView( fOwner ).ClientWidth - fHorzRuler.GetRulerHeight,
fHorzHeight ));
if GetShowBorder() then
Canvas.Pixels[ TImageEnView( fOwner ).ClientWidth - fVertWidth, fHorzHeight - 1 ] := GetThemeColor( ietpRulerBorder, clBtnShadow );
end
else
begin
// Bottom-Right
Canvas.Brush.Color := GetThemeColor( ietpRuler, GetMeasureColor );
Canvas.FillRect( Rect( TImageEnView( fOwner ).ClientWidth - fVertWidth,
TImageEnView( fOwner ).ClientHeight - fHorzHeight,
TImageEnView( fOwner ).ClientWidth,
TImageEnView( fOwner ).ClientHeight ));
Canvas.Brush.Color := GetThemeColor( ietpRulerBackground, GetColor );
Canvas.FillRect( Rect( TImageEnView( fOwner ).ClientWidth - fVertWidth,
TImageEnView( fOwner ).ClientHeight - fHorzHeight,
TImageEnView( fOwner ).ClientWidth - fVertRuler.GetRulerHeight,
TImageEnView( fOwner ).ClientHeight - fHorzRuler.GetRulerHeight ));
if GetShowBorder() then
Canvas.Pixels[ TImageEnView( fOwner ).ClientWidth - fVertWidth, TImageEnView( fOwner ).ClientHeight - fHorzHeight ] := GetThemeColor( ietpRulerBorder, clBtnShadow );
end;
end
end;
if HorzRulerVisible then
fHorzRuler.DrawToCanvas( Canvas, HorzRulerRect.Left, HorzRulerRect.Top );
if VertRulerVisible then
fVertRuler.DrawToCanvas( Canvas, VertRulerRect.Left, VertRulerRect.Top );
end;
// The horz ruler pos of the image left (always zero)
function TIEViewRulerParams.ImageLeftOnHorzRuler(): double;
begin
Result := 0;
end;
// The horz ruler pos of the image right
function TIEViewRulerParams.ImageRightOnHorzRuler(): double;
var
iev: TImageEnView;
begin
iev := TImageEnView( fOwner );
Result := ( iev.ViewX - iev.OffsetX + iev.XBmp2Scr( iev.LayersRect().Width, false )) / fHorzRuler.DotPerUnit;
end;
// The vert ruler pos of the image top (always zero)
function TIEViewRulerParams.ImageTopOnVertRuler(): double;
begin
Result := 0;
end;
// The vert ruler pos of the image Bottom
function TIEViewRulerParams.ImageBottomOnVertRuler(): double;
var
iev: TImageEnView;
begin
iev := TImageEnView( fOwner );
Result := ( iev.ViewY - iev.OffsetY + iev.YBmp2Scr( iev.LayersRect().Height, false )) / fVertRuler.DotPerUnit
end;
// Pass a ruler value, it is adjusted if SnapGrips or ConstrainGrips is enabled
function TIEViewRulerParams.ApplyHorzConstraints(value : double; DoSnapGrips : TIERulerSnapping = iesnNone; DoConstrainGrips : Boolean = False) : double;
begin
Result := value;
if Result = NON_VIZ then
exit;
case DoSnapGrips of
iesnSnapToWholeNumber : Result := Round( Value );
iesnSnapToLabel : Result := Round( value / fHorzRuler.LabelFrequency ) * fHorzRuler.LabelFrequency;
iesnSnapToTick : Result := Round( Value / fHorzRuler.Frequency ) * fHorzRuler.Frequency;
end;
if DoConstrainGrips then
begin
if Result < ImageLeftOnHorzRuler then
Result := ImageLeftOnHorzRuler;
if Result > ImageRightOnHorzRuler then
Result := ImageRightOnHorzRuler;
end;
end;
// Pass a ruler value, it is adjusted if SnapGrips or ConstrainGrips is enabled
function TIEViewRulerParams.ApplyVertConstraints(value : double; DoSnapGrips : TIERulerSnapping = iesnNone; DoConstrainGrips : Boolean = False) : double;
begin
Result := value;
if Result = NON_VIZ then
exit;
case DoSnapGrips of
iesnSnapToWholeNumber : Result := Round( Value );
iesnSnapToLabel : Result := Round( Value / fVertRuler.LabelFrequency ) * fVertRuler.LabelFrequency;
iesnSnapToTick : Result := Round( Value / fVertRuler.Frequency ) * fVertRuler.Frequency;
end;
if DoConstrainGrips then
begin
if Result < ImageTopOnVertRuler then
Result := ImageTopOnVertRuler;
if Result > ImageBottomOnVertRuler then
Result := ImageBottomOnVertRuler;
end;
end;
// Calculates the position on the ruler of a screen X value
function TIEViewRulerParams.ScrToRulerX(X : Integer) : double;
begin
Result := ( X - RulerAreaLeft ) / fHorzRuler.DotPerUnit + fHorzRuler.ViewPos;
end;
// Calculates the position on screen for a grip position (in ruler units)
function TIEViewRulerParams.RulerToScrX(Pos : Double) : Integer;
begin
result := round( fHorzRuler.DotPerUnit * ( Pos - fHorzRuler.ViewPos )) + RulerAreaLeft;
if fHorzRuler.Inverted then
result := TImageEnView( fOwner ).Width - result;
end;
// Calculates the position on the ruler of a screen Y value
// ApplyRules: adjusts if SnapGrips or ConstrainGrips is enabled
function TIEViewRulerParams.ScrToRulerY(Y : Integer) : double;
begin
Result := ( Y - RulerAreaTop ) / fVertRuler.DotPerUnit + fVertRuler.ViewPos;
end;
// Calculates the position on screen for a grip position (in ruler units)
function TIEViewRulerParams.RulerToScrY(Pos : Double) : Integer;
begin
result := round( fVertRuler.DotPerUnit * ( Pos - fVertRuler.ViewPos )) + RulerAreaTop;
if fVertRuler.Inverted then
result := TImageEnView( fOwner ).Height - result;
end;
// Converts a value adjusted by a base value to a ruler value and adjusts if SnapGrips or ConstrainGrips is enabled
function TIEViewRulerParams.ValueToRulerX(Value : double; ValueBase: TIERulerPosBase) : double;
begin
case ValueBase of
ierbBitmap : Result := ScrToRulerX( TImageEnView( fOwner ).XBmp2Scr( Round( Value ), false));
ierbScreen : Result := ScrToRulerX( Round( Value ));
else { ierbRuler } Result := Value;
end;
end;
// Converts a ruler value to a base format
function TIEViewRulerParams.RulerToValueX(Pos : double; ValueBase: TIERulerPosBase) : double;
begin
case ValueBase of
ierbBitmap : Result := TImageEnView( fOwner ).XScr2Bmp( Round( RulerToScrX( Pos{ + RulerAreaLeft} )), false);
ierbScreen : Result := Round( RulerToScrX( Pos ));
else { ierbRuler } Result := Pos;
end;
end;
// Converts a value adjusted by a base value to a ruler value and adjusts if SnapGrips or ConstrainGrips is enabled
function TIEViewRulerParams.ValueToRulerY(Value : double; ValueBase: TIERulerPosBase) : double;
begin
case ValueBase of
ierbBitmap : Result := ScrToRulerY( TImageEnView( fOwner ).YBmp2Scr( Round( Value ), false));
ierbScreen : Result := ScrToRulerY( Round( Value ));
else { ierbRuler } Result := Value;
end;
end;
// Converts a ruler value to a base format
function TIEViewRulerParams.RulerToValueY(Pos : Double; ValueBase: TIERulerPosBase) : Double;
begin
case ValueBase of
ierbBitmap : result := TImageEnView( fOwner ).YScr2Bmp( Round( RulerToScrY( Pos {+ RulerAreaTop} )), false);
ierbScreen : result := Round( RulerToScrY( Pos ));
else { ierbRuler } Result := Pos;
end;
end;
// Ensures all grips are adjusted by SnapGrips or ConstrainGrips
procedure TIEViewRulerParams.CheckGripBounds();
var
aGripsPos: TIERulerPosBase;
I: Integer;
begin
if ( fConstrainGrips = False ) and ( fSnapGrips = iesnNone ) then
exit;
aGripsPos := fGripsPosBase;
LockUpdate();
try
fGripsPosBase := ierbRuler;
for I := 0 to fHorzRuler.GripsCount - 1 do
fHorzRuler.GripsPos[ I ] := ApplyHorzConstraints( ScrToRulerX( RulerToScrX( fHorzRuler.GripsPos[ I ] )), fSnapGrips, fConstrainGrips );
for I := 0 to fVertRuler.GripsCount - 1 do
fVertRuler.GripsPos[ I ] := ApplyVertConstraints( ScrToRulerY( RulerToScrY( fVertRuler.GripsPos[ I ] )), fSnapGrips, fConstrainGrips );
finally
fGripsPosBase := aGripsPos;
UnlockUpdate();
end;
end;
// Call from TImageEnView MouseDown event
procedure TIEViewRulerParams.HandleMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if PtInRect( HorzRulerRect, Point( x, y )) then
fHorzRuler.HandleMouseDown( Button, Shift, X - HorzRulerRect.Left, Y - HorzRulerRect.Top )
else
if PtInRect( VertRulerRect, Point( x, y )) then
fVertRuler.HandleMouseDown( Button, Shift, X - VertRulerRect.Left, Y - VertRulerRect.Top )
else
begin
fHorzRuler.SelectedGrip := -1;
fHorzRuler.SelectedGrip := -1;
end;
end;
procedure TIEViewRulerParams.MouseMoveOutsideRuler(Shift: TShiftState; X, Y: Integer);
begin
if GetCursorGripKind = gkNone then
exit;
LockUpdate();
try
if fHorzRuler.GripsCount < 1 then
fHorzRuler.GripsCount := 1;
if fVertRuler.GripsCount < 1 then
fVertRuler.GripsCount := 1;
if fHorzRuler.Inverted then
X := fOwner.ClientWidth - X + RulerAreaLeft - RulerAreaRight;
if fVertRuler.Inverted then
Y := fOwner.ClientHeight - Y + RulerAreaTop - RulerAreaBottom;
// iesnNone because we don't snap cursor grips
fHorzRuler.GripsPos[ 0 ] := ApplyHorzConstraints( ScrToRulerX( X ), iesnNone, fConstrainGrips ); // Cursor grip
fVertRuler.GripsPos[ 0 ] := ApplyVertConstraints( ScrToRulerY( Y ), iesnNone, fConstrainGrips ); // Cursor grip
finally
UnlockUpdate( False, True );
end;
end;
procedure TIEViewRulerParams.ConstrainGripsCB(Sender: TObject; var GripPos: double);
begin
case TIERuler( Sender ).RulerDir of
rdHorizontal : GripPos := ApplyHorzConstraints( GripPos, fSnapGrips, fConstrainGrips );
rdVertical : GripPos := ApplyVertConstraints( GripPos, fSnapGrips, fConstrainGrips );
end;
end;
// Call from TImageEnView MouseMove event
// Result is true if mouse movement is over rulers
function TIEViewRulerParams.HandleMouseMove(Shift: TShiftState; X, Y: Integer) : Boolean;
begin
if ( TImageEnView( fOwner ).MouseCapture = False ) and
( fLastMouseMoveX = X ) and
( fLastMouseMoveY = Y ) and
( fLastMouseMoveShift = Shift ) then
begin
Result := fLastMouseMoveResult;
exit;
end;
Result := False;
{$IFDEF IEDEBUG}
OutputDebugStringW( PWideChar( Format( 'MouseMove - %d,%d', [ X, Y ])));
{$ENDIF}
// don't use PtInRect to allow them to drag outside the rect area
if ( Y >= HorzRulerRect.Top ) and ( Y <= HorzRulerRect.Bottom ) then
begin
Result := True;
fHorzRuler.HandleMouseMoveEx( Shift,
X - HorzRulerRect.Left,
Y - HorzRulerRect.Top,
ConstrainGripsCB );
end;
// Don't use else, as potentially both might need to be called
if ( X >= VertRulerRect.Left ) and ( X <= VertRulerRect.Top ) then
begin
Result := True;
fVertRuler.HandleMouseMoveEx( Shift,
X - VertRulerRect.Left,
Y - VertRulerRect.Top,
ConstrainGripsCB );
end;
if not Result then
MouseMoveOutsideRuler( Shift, X, Y );
fLastMouseMoveX := X;
fLastMouseMoveY := Y;
fLastMouseMoveShift := Shift;
fLastMouseMoveResult := Result;
end;
// Call from TImageEnView MouseUp event
procedure TIEViewRulerParams.HandleMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if PtInRect( HorzRulerRect, Point( x, y )) then
fHorzRuler.HandleMouseUp( Button, Shift, X - HorzRulerRect.Left, Y - HorzRulerRect.Top )
else
if PtInRect( VertRulerRect, Point( x, y )) then
fVertRuler.HandleMouseUp( Button, Shift, X - VertRulerRect.Left, Y - VertRulerRect.Top );
end;
procedure TIEViewRulerParams.HandleSpecialKey(CharCode: Word; Shift: TShiftState);
var
newPos, moveBy: double;
begin
if ssShift in Shift then
moveBy := fHorzRuler.LabelFrequency
else
moveBy := fHorzRuler.Frequency;
case CharCode of
VK_LEFT : if HorzRulerVisible and ( fHorzRuler.SelectedGrip > 0 ) then
begin
newPos := fHorzRuler.GripsPos[ fHorzRuler.SelectedGrip ] - moveBy;
if fConstrainGrips and ( newPos < ImageLeftOnHorzRuler ) then
newPos := ImageLeftOnHorzRuler;
fHorzRuler.GripsPos[ fHorzRuler.SelectedGrip ] := newPos;
ScrollToHorzGrip( fHorzRuler.SelectedGrip - 1 );
end;
VK_RIGHT : if HorzRulerVisible and ( fHorzRuler.SelectedGrip > 0 ) then
begin
newPos := fHorzRuler.GripsPos[ fHorzRuler.SelectedGrip ] + moveBy;
if fConstrainGrips and ( newPos > ImageRightOnHorzRuler ) then
newPos := ImageRightOnHorzRuler;
fHorzRuler.GripsPos[ fHorzRuler.SelectedGrip ] := newPos;
ScrollToHorzGrip( fHorzRuler.SelectedGrip - 1 );
end;
VK_UP : if VertRulerVisible and ( fVertRuler.SelectedGrip > 0 ) then
begin
newPos := fVertRuler.GripsPos[ fVertRuler.SelectedGrip ] - moveBy;
if fConstrainGrips and ( newPos < ImageTopOnVertRuler ) then
newPos := ImageTopOnVertRuler;
fVertRuler.GripsPos[ fVertRuler.SelectedGrip ] := newPos;
ScrollToVertGrip( fVertRuler.SelectedGrip - 1 );
end;
VK_DOWN : if VertRulerVisible and ( fVertRuler.SelectedGrip > 0 ) then
begin
newPos := fVertRuler.GripsPos[ fVertRuler.SelectedGrip ] + moveBy;
if fConstrainGrips and ( newPos > ImageBottomOnVertRuler ) then
newPos := ImageBottomOnVertRuler;
fVertRuler.GripsPos[ fVertRuler.SelectedGrip ] := newPos;
ScrollToVertGrip( fVertRuler.SelectedGrip - 1 );
end;
end;
end;
{!!
<FS>TIEViewRulerParams.HorzGripsMin
<FM>Declaration<FC>
property HorzGripsMin[g: integer]: double;
<FM>Description<FN>
Specifies the minimum position of the grip, g, on the horizontal ruler.
Use <A TIEViewRulerParams.GripsPosBase> to determine whether to pass bitmap, ruler or screen values.
Notes:
- By default, all grips are contrained to the image area (<A TIEViewRulerParams.ConstrainGrips>)
- To access the cursor grip (showing the current position of the cursor over the image), use HorzGripsMin[ -1 ]
!!}
function TIEViewRulerParams.GetHorzGripsMin(i: integer): double;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := RulerToValueX( fHorzRuler.GripsMin[ i + 1 ], fGripsPosBase );
end;
procedure TIEViewRulerParams.SetHorzGripsMin(i: integer; v: double);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fHorzRuler.GripsMin[ i + 1 ] := ValueToRulerX( v, fGripsPosBase );
end;
{!!
<FS>TIEViewRulerParams.HorzGripsMax
<FM>Declaration<FC>
property HorzGripsMax[g: integer]: double;
<FM>Description<FN>
Specifies the max position of the grip, g, on the horizontal ruler.
Use <A TIEViewRulerParams.GripsPosBase> to determine whether to pass bitmap, ruler or screen values.
Notes:
- By default, all grips are contrained to the image area (<A TIEViewRulerParams.ConstrainGrips>)
- To access the cursor grip (showing the current position of the cursor over the image), use HorzGripsMax[ -1 ]
!!}
function TIEViewRulerParams.GetHorzGripsMax(i: integer): double;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := RulerToValueX( fHorzRuler.GripsMax[ i + 1 ], fGripsPosBase );
end;
procedure TIEViewRulerParams.SetHorzGripsMax(i: integer; v: double);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fHorzRuler.GripsMax[ i + 1 ] := ValueToRulerX( v, fGripsPosBase );
end;
{!!
<FS>TIEViewRulerParams.VertGripsMin
<FM>Declaration<FC>
property VertGripsMin[g: integer]: double;
<FM>Description<FN>
Specifies the minimum position of the grip, g, on the vertical ruler.
Use <A TIEViewRulerParams.GripsPosBase> to determine whether to pass bitmap, ruler or screen values.
Notes:
- By default, all grips are contrained to the image area (<A TIEViewRulerParams.ConstrainGrips>)
- To access the cursor grip (showing the current position of the cursor over the image), use VertGripsMin[ -1 ]
!!}
function TIEViewRulerParams.GetVertGripsMin(i: integer): double;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := RulerToValueY( fVertRuler.GripsMin[ i + 1 ], fGripsPosBase );
end;
procedure TIEViewRulerParams.SetVertGripsMin(i: integer; v: double);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fVertRuler.GripsMin[ i + 1 ] := ValueToRulerY( v, fGripsPosBase );
end;
{!!
<FS>TIEViewRulerParams.VertGripsMax
<FM>Declaration<FC>
property VertGripsMax[g: integer]: double;
<FM>Description<FN>
Specifies the max position of the grip, g, on the vertical ruler.
Use <A TIEViewRulerParams.GripsPosBase> to determine whether to pass bitmap, ruler or screen values.
Notes:
- By default, all grips are contrained to the image area (<A TIEViewRulerParams.ConstrainGrips>)
- To access the cursor grip (showing the current position of the cursor over the image), use VertGripsMax[ -1 ]
!!}
function TIEViewRulerParams.GetVertGripsMax(i: integer): double;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := RulerToValueY( fVertRuler.GripsMax[ i + 1 ], fGripsPosBase );
end;
procedure TIEViewRulerParams.SetVertGripsMax(i: integer; v: double);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fVertRuler.GripsMax[ i + 1 ] := ValueToRulerY( v, fGripsPosBase );
end;
{!!
<FS>TIEViewRulerParams.MinLabelSpacing
<FM>Declaration<FC>
property MinLabelSpacing: integer;
<FM>Description<FN>
Specifies the minimum spacing between (the center of) labels. To reduce crowding, labels positioned closer than this are not shown.
If <FC>MinLabelSpacing<FN> is 0 then labels are always drawn.
Default: 30
<FM>Example<FC>
ImageEnView1.RulerParams.MinLabelSpacing := 0;
!!}
function TIEViewRulerParams.GetMinLabelSpacing: integer;
begin
result := fHorzRuler.MinLabelSpacing;
end;
procedure TIEViewRulerParams.SetMinLabelSpacing(v: integer);
begin
LockUpdate();
fHorzRuler.MinLabelSpacing := v;
fVertRuler.MinLabelSpacing := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.Frequency
<FM>Declaration<FC>
property Frequency: double;
<FM>Description<FN>
Specifies the number of logical units where ticks are shown.
Use <A TIEViewRulerParams.LabelFrequency> to configure labels and longer tick marks.
Note: This value is set automatically when changing <A TIEViewRulerParams.Units>.
Default: 10
<FM>Example<FC>
ImageEnView1.LockUpdate();
ImageEnView1.RulerParams.Units := ieruInches;
ImageEnView1.RulerParams.LabelFrequency := 1/4; // Labels every quarter inch
ImageEnView1.RulerParams.Frequency := 1/32; // Ticks every 1/32 inch
ImageEnView1.UnlockUpdate();
!!}
function TIEViewRulerParams.GetFrequency: double;
begin
result := fHorzRuler.Frequency;
end;
procedure TIEViewRulerParams.SetFrequency(v: double);
begin
LockUpdate();
fHorzRuler.Frequency := v;
fVertRuler.Frequency := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.LabelFrequency
<FM>Declaration<FC>
property LabelFrequency: double;
<FM>Description<FN>
Specifies the number of logical units where to show the labels (and longer tick marks).
Use <A TIEViewRulerParams.Frequency> to configure short tick marks.
Notes:
- This value is set automatically when changing <A TIEViewRulerParams.Units>.
- Labels may be hidden if the view is crowded and <A TIEViewRulerParams.MinLabelSpacing> has been set
Default: 40
<FM>Example<FC>
ImageEnView1.LockUpdate();
ImageEnView1.RulerParams.Units := ieruInches;
ImageEnView1.RulerParams.LabelFrequency := 1/4; // Labels every quarter inch
ImageEnView1.RulerParams.Frequency := 1/32; // Ticks every 1/32 inch
ImageEnView1.UnlockUpdate();
!!}
function TIEViewRulerParams.GetLabelFrequency: double;
begin
result := fHorzRuler.LabelFrequency;
end;
procedure TIEViewRulerParams.SetLabelFrequency(v: double);
begin
LockUpdate();
fHorzRuler.LabelFrequency := v;
fVertRuler.LabelFrequency := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.ShowMeasure
<FM>Declaration<FC>
property ShowMeasure: boolean;
<FM>Description<FN>
Specify whether a measurement block is drawn on the ruler.
Default: True
<FM>Example<FC>
// Show only grips
ImageEnView1.RulerParams.ShowMeasure := False;
ImageEnView1.RulerParams.HorzHeight := 10;
ImageEnView1.RulerParams.VertWidth := 10;
!!}
function TIEViewRulerParams.GetShowMeasure: boolean;
begin
result := fHorzRuler.ShowRuler;
end;
procedure TIEViewRulerParams.SetShowMeasure(v: boolean);
begin
LockUpdate();
fHorzRuler.ShowRuler := v;
fVertRuler.ShowRuler := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.ShowBorder
<FM>Declaration<FC>
property ShowBorder: boolean;
<FM>Description<FN>
Specify whether a border is displayed between the ruler and the image.
Default: True
<FM>Example<FC>
// Show only cursor position
ImageEnView1.RulerParams.ShowMeasure := False;
ImageEnView1.RulerParams.ShowBorder := False;
ImageEnView1.RulerParams.HorzHeight := 10;
ImageEnView1.RulerParams.VertWidth := 10;
!!}
function TIEViewRulerParams.GetShowBorder: boolean;
begin
Result := fHorzRuler.ShowBorder;
end;
procedure TIEViewRulerParams.SetShowBorder(const Value: boolean);
begin
LockUpdate();
fHorzRuler.ShowBorder := Value;
fVertRuler.ShowBorder := Value;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.MeasureColor
<FM>Declaration<FC>
property MeasureColor: TColor;
<FM>Description<FN>
Specifies the color of the <L TIEViewRulerParams.ShowMeasure>measurement block</L> of the ruler.
Note: This value may be overridden if <A TIEImageEnGlobalSettings.EnableTheming> is enabled.
Default: clBtnFace
<FM>See Also<FN>
- <A TIEViewRulerParams.Color>
!!}
function TIEViewRulerParams.GetMeasureColor: TColor;
begin
result := fHorzRuler.RulerColor;
end;
procedure TIEViewRulerParams.SetMeasureColor(v: TColor);
begin
LockUpdate();
fHorzRuler.RulerColor := v;
fVertRuler.RulerColor := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.Color
<FM>Declaration<FC>
property Color: TColor;
<FM>Description<FN>
Specifies the color of the background (excluding area of the <L TIEViewRulerParams.ShowMeasure>measurement block</L>).
Note: This value may be overridden if <A TIEImageEnGlobalSettings.EnableTheming> is enabled.
Default: clBtnShadow
<FM>See Also<FN>
- <A TIEViewRulerParams.MeasureColor>
!!}
// return -1 = none
function TIEViewRulerParams.GetColor: TColor;
begin
result := fHorzRuler.Background;
end;
procedure TIEViewRulerParams.SetColor(c: TColor);
begin
LockUpdate();
fHorzRuler.Background := c;
fVertRuler.Background := c;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.HorzInverted
<FM>Declaration<FC>
property HorzInverted: boolean;
<FM>Description<FN>
When true, the horizontal ruler is painted from right to left.
Default: False
<FM>Example<FC>
// Draw a right-hand side UI
ImageEnView1.LockUpdate();
ImageEnView1.ShowRulers := [ rdVertical, rdHorizontal ];
ImageEnView1.RulerParams.VertPos := gdRight; // Ruler on RHS
ImageEnView1.RulerParams.HorzInverted := True; // Horz ruler reversed measurement
ImageEnView1.UnlockUpdate();
<FM>See Also<FN>
- <A TIEViewRulerParams.VertInverted>
- <A TIEViewRulerParams.HorzPos>
- <A TIEViewRulerParams.VertPos>
!!}
function TIEViewRulerParams.GetHorzInverted: boolean;
begin
result := fHorzRuler.Inverted;
end;
procedure TIEViewRulerParams.SetHorzInverted(v: boolean);
begin
fHorzRuler.Inverted := v;
end;
{!!
<FS>TIEViewRulerParams.VertInverted
<FM>Declaration<FC>
property VertInverted: boolean;
<FM>Description<FN>
When true, the vertical ruler is painted from bottom to top.
Default: False.
<FM>Example<FC>
// Draw ruler from bottom to top
ImageEnView1.RulerParams.VertInverted := True;
<FM>See Also<FN>
- <A TIEViewRulerParams.HorzInverted>
- <A TIEViewRulerParams.HorzPos>
- <A TIEViewRulerParams.VertPos>
!!}
function TIEViewRulerParams.GetVertInverted: boolean;
begin
result := fVertRuler.Inverted;
end;
procedure TIEViewRulerParams.SetVertInverted(v: boolean);
begin
fVertRuler.Inverted := v;
end;
{!!
<FS>TIEViewRulerParams.LabelPrecision
<FM>Declaration<FC>
property LabelPrecision: integer;
<FM>Description<FN>
Specifies the number of decimal places shown for values in the ruler.
Default: 2
<FM>Example<FC>
ImageEnView1.LockUpdate();
ImageEnView1.RulerParams.Units := ieruCentimeters;
ImageEnView1.RulerParams.LabelPrecision := 1; // Show labels to one decimal place
ImageEnView1.UnlockUpdate();
!!}
function TIEViewRulerParams.GetLabelPrecision: integer;
begin
result := fHorzRuler.LabelPrecision;
end;
procedure TIEViewRulerParams.SetLabelPrecision(v: integer);
begin
LockUpdate();
fHorzRuler.LabelPrecision := v;
fVertRuler.LabelPrecision := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.ScrollRate
<FM>Declaration<FC>
property ScrollRate: double;
<FM>Description<FN>
Specifies the scroll rate used when moving a grip out of ruler borders.
Default: 1.0
!!}
function TIEViewRulerParams.GetScrollRate: double;
begin
result := fHorzRuler.ScrollRate;
end;
procedure TIEViewRulerParams.SetScrollRate(const Value: double);
begin
fHorzRuler.ScrollRate := Value;
fVertRuler.ScrollRate := Value;
end;
{!!
<FS>TIEViewRulerParams.CursorGripKind
<FM>Declaration<FC>
property CursorGripKind: <A TGripKind>;
<FM>Description<FN>
Specifies the style for the grip that appears on the ruler showing the current position of the cursor over the image.
Default: gkLine
Note: You can access other properties of the cursor grips, using index -1 in the horizontal and vertical grip arrays.
i.e.
<FC>
ImageEnView1.RulerParams.CursorGripKind := gkTriangle;
<FN>
Is the same as setting:
<FC>
ImageEnView1.RulerParams.HorzGripsKind[ -1 ] := gkTriangle;
ImageEnView1.RulerParams.VertGripsKind[ -1 ] := gkTriangle;<FN>
<FM>Example<FC>
// Hide the cursor grip
ImageEnView1.RulerParams.CursorGripKind := gkNone;
// Set the cursor grip to a red triangle
ImageEnView1.RulerParams.CursorGripKind := gkTriangle;
ImageEnView1.RulerParams.HorzGripsColor[ -1 ] := clRed;
ImageEnView1.RulerParams.VertGripsColor[ -1 ] := clRed;
<FM>See Also<FC>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.GripPenColor>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
!!}
function TIEViewRulerParams.GetCursorGripKind: TGripKind;
begin
result := GetHorzGripsKind( -1 );
end;
procedure TIEViewRulerParams.SetCursorGripKind(const Value: TGripKind);
begin
SetHorzGripsKind( -1, Value );
SetVertGripsKind( -1, Value );
end;
{!!
<FS>TIEViewRulerParams.GripKindDefault
<FM>Declaration<FC>
property GripKindDefault: <A TGripKind>;
<FM>Description<FN>
Specifies the default style for all grips.
This style will be assigned to any grips for which you have not set a custom style using <A TIEViewRulerParams.HorzGripsKind> or <A TIEViewRulerParams.VertGripsKind>.
Notes:
- The size of the grip is specified by <A TIEViewRulerParams.GripWidth> and <A TIEViewRulerParams.GripHeight>.
- This property does not affect the grip for the current cursor position, use <A TIEViewRulerParams.CursorGripKind> instead
Default: gkTriangle
<FM>Example<FC>
// Set default style of grips to gkTriangle, but gkArrow2 to grips > 10
ImageEnView1.RulerParams.GripKindDefault := gkTriangle;
for i := 10 to ImageEnView1.RulerParams.HorzGripsCount - 1 do
ImageEnView1.RulerParams.HorzGripsKind[ i ] := gkArrow2;
<FM>See Also<FN>
- <A TIEViewRulerParams.HorzGripsKind>
- <A TIEViewRulerParams.VertGripsKind>
- <A TIEViewRulerParams.CursorGripKind>
- <A TIEViewRulerParams.GripPenColor>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
!!}
function TIEViewRulerParams.GetGripKindDefault: TGripKind;
begin
result := fHorzRuler.GripKindDefault;
end;
procedure TIEViewRulerParams.SetGripKindDefault(const Value: TGripKind);
begin
LockUpdate();
fHorzRuler.GripKindDefault := Value;
fVertRuler.GripKindDefault := Value;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.GripColorDefault
<FM>Declaration<FC>
property GripColorDefault: TColor;
<FM>Description<FN>
Specifies the brush color of all grips.
This color will be assigned to any grips for which you have not set a custom color using <A TIEViewRulerParams.HorzGripsColor> or <A TIEViewRulerParams.VertGripsColor>.
Notes:
- This value may be overridden if <A TIEImageEnGlobalSettings.EnableTheming> is enabled.
- You can set the pen color with <A TIEViewRulerParams.GripPenColor>
Default: cl3DLight
<FM>Example<FC>
// Set default color of grips to clSilver, but clRed to grips > 10
ImageEnView1.RulerParams.GripColorDefault := clSilver;
for i := 10 to ImageEnView1.RulerParams.HorzGripsCount - 1 do
ImageEnView1.RulerParams.HorzGripsColor[ i ] := clRed;
<FM>See Also<FN>
- <A TIEViewRulerParams.GripPenColor>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
!!}
function TIEViewRulerParams.GetGripColorDefault: TColor;
begin
result := fHorzRuler.GripColorDefault;
end;
procedure TIEViewRulerParams.SetGripColorDefault(const Value: TColor);
begin
LockUpdate();
fHorzRuler.GripColorDefault := Value;
fVertRuler.GripColorDefault := Value;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.GripPenColor
<FM>Declaration<FC>
property GripPenColor: TColor;
<FM>Description<FN>
Specifies the pen (border) color of all grips.
Notes:
- This value may be overridden if <A TIEImageEnGlobalSettings.EnableTheming> is enabled.
- The brush color is specified by <A TIEViewRulerParams.GripColorDefault>, or for individual grips with <A TIEViewRulerParams.HorzGripsColor> or <A TIEViewRulerParams.VertGripsColor>.
Default: clWindowFrame
<FM>See Also<FN>
- <A TIEViewRulerParams.HorzGripsColor>
- <A TIEViewRulerParams.VertGripsColor>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
!!}
function TIEViewRulerParams.GetGripPenColor: TColor;
begin
result := fHorzRuler.GripPenColor;
end;
procedure TIEViewRulerParams.SetGripPenColor(const Value: TColor);
begin
LockUpdate();
fHorzRuler.GripPenColor := Value;
fVertRuler.GripPenColor := Value;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.GripWidth
<FM>Declaration<FC>
property GripWidth: integer;
<FM>Description<FN>
Specifies the width of grip triangles in pixels.
Default: 12
<FM>See Also<FN>
- <A TIEViewRulerParams.GripHeight>
- <A TIEViewRulerParams.GripKindDefault>
!!}
function TIEViewRulerParams.GetGripWidth: integer;
begin
result := fHorzRuler.GripBaseDim;
end;
procedure TIEViewRulerParams.SetGripWidth(v: integer);
begin
LockUpdate();
fHorzRuler.GripBaseDim := v;
fVertRuler.GripBaseDim := v;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.GripHeight
<FM>Declaration<FC>
property GripHeight: integer;
<FM>Description<FN>
Specifies the maximum height of the grip.
Default: 15
Note: The value may be automatically adjusted depending on your <L TIEViewRulerParams.Font>font size</L> and the available <L TIEViewRulerParams.HorzHeight>height</L>/<L TIEViewRulerParams.VertWidth>width</L>.
<FM>Example<FC>
// Create narrow rulers
ImageEnView1.RulerParams.Font.Size := 6;
ImageEnView1.RulerParams.HorzHeight := 20;
ImageEnView1.RulerParams.VertWidth := 20;
ImageEnView1.RulerParams.GripHeight := 10;
<FM>See Also<FN>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripKindDefault>
!!}
function TIEViewRulerParams.GetGripHeight: integer;
begin
result := fHorzRuler.MaxGripHeight;
end;
procedure TIEViewRulerParams.SetGripHeight(const Value: integer);
begin
LockUpdate();
fHorzRuler.MaxGripHeight := Value;
fVertRuler.MaxGripHeight := Value;
UnlockUpdate();
end;
{!!
<FS>TIEViewRulerParams.HorzGripsPos
<FM>Declaration<FC>
property HorzGripsPos[g: integer]: double;
<FM>Description<FN>
Specifies the current position of the grip, g, on the horizontal ruler.
Use <A TIEViewRulerParams.GripsPosBase> to determine whether to pass bitmap, ruler or screen values.
<FM>Example<FC>
// Add three grips at 25%, 50% and 75% of the image width
ImageEnView1.RulerParams.HorzGripsCount := 3;
ImageEnView1.RulerParams.GripsPosBase := ierbBitmap; // Units are relative to the bitmap
ImageEnView1.RulerParams.HorzGripsPos[ 0 ] := MulDiv( ImageEnView1.IEBitmap.Width, 1, 4 );
ImageEnView1.RulerParams.HorzGripsPos[ 1 ] := MulDiv( ImageEnView1.IEBitmap.Width, 2, 4 );
ImageEnView1.RulerParams.HorzGripsPos[ 2 ] := MulDiv( ImageEnView1.IEBitmap.Width, 3, 4 );
!!}
function TIEViewRulerParams.GetHorzGripsPos(i: integer): double;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := RulerToValueX( fHorzRuler.GripsPos[ i + 1 ], fGripsPosBase );
end;
procedure TIEViewRulerParams.SetHorzGripsPos(i: integer; p: double);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fHorzRuler.GripsPos[ i + 1 ] := ApplyHorzConstraints( ValueToRulerX( p, fGripsPosBase ), fSnapGrips, fConstrainGrips );
end;
{!!
<FS>TIEViewRulerParams.HorzGripsCount
<FM>Declaration<FC>
property HorzGripsCount: integer;
<FM>Description<FN>
Specifies the number of the grips on the horizontal ruler.
Default: 0
<FM>Examples<FC>
// Clear added grips
ImageEnView1.RulerParams.HorzGripsCount := 0;
// Add twenty grips
ImageEnView1.RulerParams.HorzGripsCount := 20;
// Set default color of grips to clSilver, but clRed for grips > 10
ImageEnView1.RulerParams.GripColorDefault := clSilver;
for i := 10 to ImageEnView1.RulerParams.HorzGripsCount - 1 do
ImageEnView1.RulerParams.HorzGripsColor[ i ] := clRed;
!!}
function TIEViewRulerParams.GetHorzGripsCount: integer;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := fHorzRuler.GripsCount - 1;
end;
procedure TIEViewRulerParams.SetHorzGripsCount(v: integer);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fHorzRuler.GripsCount := imax( 1, v + 1 );
end;
{!!
<FS>TIEViewRulerParams.HorzGripsKind
<FM>Declaration<FC>
property HorzGripsKind[g: integer]: <A TGripKind>;
<FM>Description<FN>
Specifies the style of the grip, g, on the horizontal ruler (triangle, arrow, etc).
Notes:
- The default style for grips is specified by <A TIEViewRulerParams.GripKindDefault>. Use <A TIEViewRulerParams.HorzGripsKind> when you want individual grips with different styles
- The style of the grip showing the current cursor position is specified by <A TIEViewRulerParams.CursorGripKind>
- The size of the grip is specified by <A TIEViewRulerParams.GripWidth> and <A TIEViewRulerParams.GripHeight>
<FM>Examples<FC>
// Set default style of grips to gkTriangle, but gkArrow2 to grips > 10
ImageEnView1.RulerParams.GripKindDefault := gkTriangle;
for i := 10 to ImageEnView1.RulerParams.HorzGripsCount - 1 do
ImageEnView1.RulerParams.HorzGripsKind[ i ] := gkArrow2;
<FM>See Also<FN>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.VertGripsKind>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.GripPenColor>
!!}
function TIEViewRulerParams.GetHorzGripsKind(i: integer): TGripKind;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := fHorzRuler.GripsKind[ i + 1 ];
end;
procedure TIEViewRulerParams.SetHorzGripsKind(i: integer; v: TGripKind);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fHorzRuler.GripsKind[ i + 1 ] := v;
end;
{!!
<FS>TIEViewRulerParams.HorzGripsColor
<FM>Declaration<FC>
property HorzGripsColor[g: integer]: TColor;
<FM>Description<FN>
Specifies the brush color of the grip, g, on the horizontal ruler.
Notes:
- The default color of all grips is set by <A TIEViewRulerParams.GripColorDefault>. Use <FC>HorzGripsColor<FN> to assign custom colors to specific grips.
- To access the cursor grip (showing the current position of the cursor over the image), use HorzGripsColor[ -1 ]
You can set the pen color with <A TIEViewRulerParams.GripPenColor>
<FM>Example<FC>
// Set default color of grips to clSilver, but clRed for grips > 10
ImageEnView1.RulerParams.GripColorDefault := clSilver;
for i := 10 to ImageEnView1.RulerParams.HorzGripsCount - 1 do
ImageEnView1.RulerParams.HorzGripsColor[ i ] := clRed;
// Set the cursor grip to a red triangle
ImageEnView1.RulerParams.HorzGripsKind[ -1 ] := gkTriangle; // Same as setting CursorGripKind
ImageEnView1.RulerParams.HorzGripsColor[ -1 ] := clRed;
<FM>See Also<FN>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.VertGripsColor>
- <A TIEViewRulerParams.GripPenColor>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
!!}
function TIEViewRulerParams.GetHorzGripsColor(i: integer): TColor;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := fHorzRuler.GripsColor[ i + 1 ];
end;
procedure TIEViewRulerParams.SetHorzGripsColor(i: integer; p: TColor);
begin
fHorzRuler.GripsColor[ i + 1 ] := p;
end;
{!!
<FS>TIEViewRulerParams.VertGripsPos
<FM>Declaration<FC>
property VertGripsPos[g: integer]: double;
<FM>Description<FN>
Specifies the current position of the grip, g, on the vertical ruler.
Use <A TIEViewRulerParams.GripsPosBase> to determine whether to pass bitmap, ruler or screen values.
<FM>Example<FC>
// Add three grips at 25%, 50% and 75% of the image height
ImageEnView1.RulerParams.VertGripsCount := 3;
ImageEnView1.RulerParams.GripsPosBase := ierbBitmap; // Units are relative to the bitmap
ImageEnView1.RulerParams.VertGripsPos[ 0 ] := MulDiv( ImageEnView1.IEBitmap.Height, 1, 4 );
ImageEnView1.RulerParams.VertGripsPos[ 1 ] := MulDiv( ImageEnView1.IEBitmap.Height, 2, 4 );
ImageEnView1.RulerParams.VertGripsPos[ 2 ] := MulDiv( ImageEnView1.IEBitmap.Height, 3, 4 );
!!}
function TIEViewRulerParams.GetVertGripsPos(i: integer): double;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := RulerToValueY( fVertRuler.GripsPos[ i + 1 ], fGripsPosBase );
end;
procedure TIEViewRulerParams.SetVertGripsPos(i: integer; p: double);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fVertRuler.GripsPos[ i + 1 ] := ApplyVertConstraints(ValueToRulerY( p, fGripsPosBase ), fSnapGrips, fConstrainGrips );
end;
{!!
<FS>TIEViewRulerParams.VertGripsCount
<FM>Declaration<FC>
property VertGripsCount: integer;
<FM>Description<FN>
Specifies the number of the grips on the vertical ruler.
Default: 0
<FM>Examples<FC>
// Clear all grips
ImageEnView1.RulerParams.VertGripsCount := 0;
// Add twenty grips
ImageEnView1.RulerParams.VertGripsCount := 20;
// Set default color of grips to clSilver, but clRed for grips > 10
ImageEnView1.RulerParams.GripColorDefault := clSilver;
for i := 10 to ImageEnView1.RulerParams.VertGripsCount - 1 do
ImageEnView1.RulerParams.VertGripsColor[ i ] := clRed;
!!}
function TIEViewRulerParams.GetVertGripsCount: integer;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := fVertRuler.GripsCount - 1;
end;
procedure TIEViewRulerParams.SetVertGripsCount(v: integer);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fVertRuler.GripsCount := imax( 1, v + 1 )
end;
{!!
<FS>TIEViewRulerParams.VertGripsKind
<FM>Declaration<FC>
property VertGripsKind[g: integer]: <A TGripKind>;
<FM>Description<FN>
Specifies the style of the grip, g, on the vertical ruler (triangle, arrow, etc).
Notes:
- The default style for grips is specified by <A TIEViewRulerParams.GripKindDefault>. Use <A TIEViewRulerParams.VertGripsKind> when you want individual grips with different styles
- The style of the grip showing the current cursor position is specified by <A TIEViewRulerParams.CursorGripKind>
- The size of the grip is specified by <A TIEViewRulerParams.GripWidth> and <A TIEViewRulerParams.GripHeight>
<FM>Example<FC>
// Set default style of grips to gkTriangle, but gkArrow2 to grips > 10
ImageEnView1.RulerParams.GripKindDefault := gkTriangle;
for i := 10 to ImageEnView1.RulerParams.VertGripsCount - 1 do
ImageEnView1.RulerParams.VertGripsKind[ i ] := gkArrow2;
// Set the cursor grip to a red triangle
ImageEnView1.RulerParams.VertGripsKind[ -1 ] := gkTriangle; // Same as setting CursorGripKind
ImageEnView1.RulerParams.VertGripsColor[ -1 ] := clRed;
<FM>See Also<FN>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.HorzGripsKind>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.GripPenColor>
!!}
function TIEViewRulerParams.GetVertGripsKind(i: integer): TGripKind;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := fVertRuler.GripsKind[ i + 1 ];
end;
procedure TIEViewRulerParams.SetVertGripsKind(i: integer; v: TGripKind);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fVertRuler.GripsKind[ i + 1 ] := v;
end;
{!!
<FS>TIEViewRulerParams.VertGripsColor
<FM>Declaration<FC>
property VertGripsColor[g: integer]: TColor;
<FM>Description<FN>
Specifies the brush color of the grip, g, on the vertical ruler.
Notes:
- The default color of all grips is set by <A TIEViewRulerParams.GripColorDefault>. Use <FC>VertGripsColor<FN> to assign custom colors to specific grips.
- To access the cursor grip (showing the current position of the cursor over the image), use VertGripsColor[ -1 ]
You can set the pen color with <A TIEViewRulerParams.GripPenColor>
<FM>Example<FC>
// Set default color of grips to clSilver, but clRed for grips > 10
ImageEnView1.RulerParams.GripColorDefault := clSilver;
for i := 10 to ImageEnView1.RulerParams.VertGripsCount - 1 do
ImageEnView1.RulerParams.VertGripsColor[ i ] := clRed;
<FM>See Also<FN>
- <A TIEViewRulerParams.GripColorDefault>
- <A TIEViewRulerParams.HorzGripsColor>
- <A TIEViewRulerParams.GripPenColor>
- <A TIEViewRulerParams.GripKindDefault>
- <A TIEViewRulerParams.GripWidth>
- <A TIEViewRulerParams.GripHeight>
!!}
function TIEViewRulerParams.GetVertGripsColor(i: integer): TColor;
begin
// Offset index by 1 to obscure grip 0, the cursor grip
result := fVertRuler.GripsColor[ i + 1 ];
end;
procedure TIEViewRulerParams.SetVertGripsColor(i: integer; p: TColor);
begin
// Offset index by 1 to obscure grip 0, the cursor grip
fVertRuler.GripsColor[ i + 1 ] := p;
end;
{!!
<FS>TIEViewRulerParams.Font
<FM>Declaration<FC>
property Font: TFont;
<FM>Description<FN>
Specifies the font used for label text.
Note: The color of this font may be overridden if <A TIEImageEnGlobalSettings.EnableTheming> is enabled.
<FM>Example<FC>
// Create narrow rulers
ImageEnView1.RulerParams.Font.Size := 6;
ImageEnView1.RulerParams.HorzHeight := 20;
ImageEnView1.RulerParams.VertWidth := 20;
ImageEnView1.RulerParams.GripHeight := 10;
!!}
function TIEViewRulerParams.GetFont: TFont;
begin
result := fHorzRuler.Font;
end;
procedure TIEViewRulerParams.FontChange(Sender: TObject);
begin
fVertRuler.Font.Assign( Font );
end;
{!!
<FS>TIEViewRulerParams.SnapGrips
<FM>Declaration<FC>
property SnapGrips: <A TIERulerSnapping>;
<FM>Description<FN>
Specifies whether grips snap to the closest label or whole number on the ruler.
<FM>Description<FN>
<TABLE>
<R> <H>Item</H> <H>Description</H> </R>
<R> <C><FC>iesnNone<FN></C> <C>Do not adjust grip positions</C> </R>
<R> <C><FC>iesnSnapToTick<FN></C> <C>Automatically move grips to the nearest <L TIEViewRulerParams.Frequency>tick</L></C> </R>
<R> <C><FC>iesnSnapToLabel<FN></C> <C>Automatically move grips to the nearest <L TIEViewRulerParams.LabelFrequency>label</L> (long tick)</C> </R>
<R> <C><FC>iesnSnapToWholeNumber<FN></C> <C>Automatically move grips to the nearest whole value on the ruler (e.g. move to 2.0 inches)</C> </R>
</TABLE>
Default: iesnNone
<FM>Example<FC>
// Snap to the nearest label tick
ImageEnView1.RulerParams.SnapGrips := iesnSnapToLabel;
// Snap to the nearest whole number on the ruler
ImageEnView1.RulerParams.SnapGrips := iesnSnapToWholeNumber;
!!}
procedure TIEViewRulerParams.SetSnapGrips(Value: TIERulerSnapping);
begin
fSnapGrips := Value;
// Snap existing grips
CheckGripBounds();
end;
{!!
<FS>TIEViewRulerParams.ConstrainGrips
<FM>Declaration<FC>
property ConstrainGrips: Boolean;
<FM>Description<FN>
Specifies whether grips can be dragged outside the area of the image.
Default: True
<FM>Example<FC>
// Allow dragging of grips outside the area of the image
ImageEnView1.RulerParams.ConstrainGrips := False;
!!}
procedure TIEViewRulerParams.SetConstrainGrips(Value: Boolean);
begin
fConstrainGrips := Value;
// Constrain existing grips
CheckGripBounds();
end;
{!!
<FS>TIEViewRulerParams.AlignToImage
<FM>Declaration<FC>
property AlignToImage: Boolean;
<FM>Description<FN>
If false, the ruler will be the full width of the control (and show negative values for areas outside the image). If true, the ruler begins at the position of the image within the control.
Default: False
!!}
procedure TIEViewRulerParams.SetAlignToImage(Value: Boolean);
begin
fAlignToImage := Value;
Update();
end;
{!!
<FS>TIEViewRulerParams.Units
<FM>Declaration<FC>
property Units: <A TIERulerUnits>;
<FM>Description<FN>
Specifies the measurement unit displayed on the ruler.
Default: ieruPixels
Note: Changing <FC>Units<FN> will automatically set <A TIEViewRulerParams.LabelFrequency> and <A TIEViewRulerParams.Frequency> to a relevant value
<FM>Example<FC>
ImageEnView1.LockUpdate();
ImageEnView1.RulerParams.Units := ieruInches;
ImageEnView1.RulerParams.LabelFrequency := 1/4; // Labels every quarter inch
ImageEnView1.RulerParams.Frequency := 1/32; // Ticks every 1/32 inch
ImageEnView1.UnlockUpdate();
!!}
procedure TIEViewRulerParams.SetUnits(Value: TIERulerUnits);
var
lfrq, tfrq: double;
begin
if fUnits = Value then
exit;
LockUpdate();
try
fUnits := Value;
case fUnits of
ieruInches:
begin
lfrq := 0.25; // Every quarter inch
tfrq := lfrq / 8;
end;
ieruMillimeters:
begin
lfrq := 2.5; // Every 2.5 mm
tfrq := lfrq / 5;
end;
ieruCentimeters:
begin
lfrq := 0.25; // Every quarter CM
tfrq := lfrq / 5;
end;
else { ieruPixels }
begin
lfrq := 100; // Every 100px
tfrq := lfrq / 10;
end;
end;
fHorzRuler.Frequency := tfrq;
fVertRuler.Frequency := tfrq;
fHorzRuler.LabelFrequency := lfrq;
fVertRuler.LabelFrequency := lfrq;
finally
UnlockUpdate();
end;
end;
{!!
<FS>TIEViewRulerParams.HorzPos
<FM>Declaration<FC>
property HorzPos: <A TGripsDir>;
<FM>Description<FN>
Specifies Whether the horizontal ruler is shown above (gdUp) or below (gdDown) the image.
Default: gdUp
<FM>Example<FC>
// Draw a horizontal ruler on bottom of image
ImageEnView1.LockUpdate();
ImageEnView1.ShowRulers := [ rdHorizontal ];
ImageEnView1.RulerParams.VertPos := gdDown;
ImageEnView1.UnlockUpdate();
<FM>See Also<FC>
- <A TIEViewRulerParams.VertPos>
- <A TIEViewRulerParams.HorzInverted>
- <A TIEViewRulerParams.VertInverted>
!!}
procedure TIEViewRulerParams.SetHorzPos(Value: TGripsDir);
begin
if fHorzPos <> Value then
begin
fHorzPos := Value;
fHorzRuler.GripsDir := Value;
TImageEnView( fOwner).Update();
end;
end;
{!!
<FS>TIEViewRulerParams.VertPos
<FM>Declaration<FC>
property VertPos: <A TGripsXDir>;
<FM>Description<FN>
Specifies whether the vertical ruler is shown left (gdLeft) or right (gdRight) of the image.
Default: gdLeft
<FM>Example<FC>
// Draw a vertical ruler on right of image
ImageEnView1.LockUpdate();
ImageEnView1.ShowRulers := [ rdVertical ];
ImageEnView1.RulerParams.VertPos := gdRight;
ImageEnView1.UnlockUpdate();
<FM>See Also<FC>
- <A TIEViewRulerParams.HorzPos>
- <A TIEViewRulerParams.HorzInverted>
- <A TIEViewRulerParams.VertInverted>
!!}
procedure TIEViewRulerParams.SetVertPos(Value: TGripsXDir);
begin
if fVertPos <> Value then
begin
fVertPos := Value;
fVertRuler.GripsDir := TGripsDir( ord( Value ));
TImageEnView( fOwner).Update();
end;
end;
{!!
<FS>TIEViewRulerParams.HorzHeight
<FM>Declaration<FC>
property HorzHeight: Integer;
<FM>Description<FN>
Specifies the height of the horizontal ruler.
Default: 40
<FM>Example<FC>
// Create narrow rulers
ImageEnView1.RulerParams.Font.Size := 6;
ImageEnView1.RulerParams.HorzHeight := 20;
ImageEnView1.RulerParams.VertWidth := 20;
ImageEnView1.RulerParams.GripHeight := 10;
!!}
procedure TIEViewRulerParams.SetHorzHeight(Value: Integer);
begin
if fHorzHeight <> Value then
begin
fHorzHeight := Value;
TImageEnView( fOwner).Update();
end;
end;
{!!
<FS>TIEViewRulerParams.VertWidth
<FM>Declaration<FC>
property VertWidth: Integer;
<FM>Description<FN>
Specifies the width of the vertical ruler.
Default: 40
<FM>Example<FC>
// Create narrow rulers
ImageEnView1.RulerParams.Font.Size := 6;
ImageEnView1.RulerParams.HorzHeight := 20;
ImageEnView1.RulerParams.VertWidth := 20;
ImageEnView1.RulerParams.GripHeight := 10;
!!}
procedure TIEViewRulerParams.SetVertWidth(Value: Integer);
begin
if fVertWidth <> Value then
begin
fVertWidth := Value;
TImageEnView( fOwner).Update();
end;
end;
function TIEViewRulerParams.GetHorzRulerRect: TRect;
var
rLeft, rRight, rTop, rBottom: Integer;
begin
rLeft := 0;
rRight := -1;
rTop := 0;
rBottom := -1;
if VertRulerVisible then
begin
if fHorzPos = gdUp then
begin
// Top
rTop := 0;
rBottom := fHorzHeight;
end
else
begin
// Bottom
rTop := TImageEnView( fOwner ).ClientHeight - fHorzHeight ;
rBottom := TImageEnView( fOwner ).ClientHeight ;
end;
rLeft := 0;
if VertRulerVisible and ( fVertPos = gdLeft ) then
rLeft := fVertWidth;
rRight := TImageEnView( fOwner ).ClientWidth ;
if VertRulerVisible and ( fVertPos <> gdLeft ) then
rRight := TImageEnView( fOwner ).ClientWidth - fVertWidth ;
end;
Result := Rect( rLeft, rTop, rRight, rBottom );
end;
function TIEViewRulerParams.GetVertRulerRect: TRect;
var
rLeft, rRight, rTop, rBottom: Integer;
begin
rLeft := 0;
rRight := -1;
rTop := 0;
rBottom := -1;
if VertRulerVisible then
begin
if fVertPos = gdLeft then
begin
// Left
rLeft := 0;
rRight := fVertWidth;
end
else
begin
// Right
rLeft := TImageEnView( fOwner ).ClientWidth - fVertWidth ;
rRight := TImageEnView( fOwner ).ClientWidth ;
end;
rTop := 0;
if HorzRulerVisible and ( fHorzPos = gdUp ) then
rTop := fHorzHeight;
rBottom := TImageEnView( fOwner ).ClientHeight ;
if HorzRulerVisible and ( fHorzPos = gdDown ) then
rBottom := TImageEnView( fOwner ).ClientHeight - fHorzHeight ;
end;
Result := Rect( rLeft, rTop, rRight, rBottom );
end;
function TIEViewRulerParams.RulerAreaLeft: Integer;
begin
Result := 0;
if VertRulerVisible and ( fVertPos = gdLeft ) then
Result := fVertWidth;
end;
function TIEViewRulerParams.RulerAreaRight: Integer;
begin
Result := 0;
if VertRulerVisible and ( fVertPos = gdRight ) then
Result := fVertWidth;
end;
function TIEViewRulerParams.RulerAreaTop: Integer;
begin
Result := 0;
if HorzRulerVisible and ( fHorzPos = gdUp ) then
Result := fHorzHeight;
end;
function TIEViewRulerParams.RulerAreaBottom: Integer;
begin
Result := 0;
if HorzRulerVisible and ( fHorzPos = gdDown ) then
Result := fHorzHeight;
end;
function TIEViewRulerParams.HorzRulerVisible: Boolean;
begin
Result := rdHorizontal in TImageEnView( fOwner ).ShowRulers;
end;
function TIEViewRulerParams.VertRulerVisible: Boolean;
begin
Result := rdVertical in TImageEnView( fOwner ).ShowRulers;
end;
// Bring grip g into view
procedure TIEViewRulerParams.ScrollToHorzGrip(g: Integer);
var
z: Double;
iev: TImageEnView;
X: Integer;
begin
iev := TImageEnView( fOwner );
z := iev.Zoom / 100;
X := round( RulerToValueX( fHorzRuler.GripsPos[ g + 1 ], ierbBitmap ));
if X < round( iev.ViewX / iev.Zoom * 100 ) then
iev.ViewX := round( X * z )
else
if X > round(( iev.ViewX + iev.ExtentX ) / iev.Zoom * 100 ) then
iev.ViewX := Round(( X - round( iev.ExtentX / iev.Zoom * 100 )) * z ) ;
end;
// Bring grip g into view
procedure TIEViewRulerParams.ScrollToVertGrip(g: Integer);
var
z: Double;
iev: TImageEnView;
Y: Integer;
begin
iev := TImageEnView( fOwner );
z := iev.Zoom / 100;
Y := round( RulerToValueY( fVertRuler.GripsPos[ g + 1 ], ierbBitmap ));
if Y < round( iev.ViewY / iev.Zoom * 100 ) then
iev.ViewY := round( Y * z )
else
if Y > round(( iev.ViewY + iev.ExtentY ) / iev.Zoom * 100 ) then
iev.ViewY := Round(( Y - round( iev.ExtentY / iev.Zoom * 100 )) * z ) ;
end;
// Call from TImageEnView.LockUpdate
procedure TIEViewRulerParams.LockUpdate();
begin
fHorzRuler.LockUpdate();
fVertRuler.LockUpdate();
end;
// Call from TImageEnView.UnlockUpdate
procedure TIEViewRulerParams.UnlockUpdate(DoUpdate: Boolean = True; DoInvalidate: Boolean = True);
begin
fHorzRuler.UnlockUpdate( DoUpdate, False );
fVertRuler.UnlockUpdate( DoUpdate, False );
if DoUpdate and ( fHorzRuler.LockUpdateCount <= 0 ) then
Update( DoInvalidate )
else
if DoInvalidate and ( HorzRulerVisible or VertRulerVisible ) then
fOwner.Invalidate();
end;
function TIEViewRulerParams.GetOnRulerClick: TRulerClickEvent;
begin
result := fHorzRuler.fOnRulerClick;
end;
procedure TIEViewRulerParams.SetOnRulerClick(const Value: TRulerClickEvent);
begin
fHorzRuler.fOnRulerClick := Value;
fVertRuler.fOnRulerClick := Value;
end;
function TIEViewRulerParams.GetOnRulerGripClick: TRulerGripClickEvent;
begin
result := fHorzRuler.fOnRulerGripClick;
end;
procedure TIEViewRulerParams.SetOnRulerGripClick(const Value: TRulerGripClickEvent);
begin
fHorzRuler.fOnRulerGripClick := Value;
fVertRuler.fOnRulerGripClick := Value;
end;
function TIEViewRulerParams.GetOnRulerGripDblClick: TRulerGripClickEvent;
begin
result := fHorzRuler.fOnRulerGripDblClick;
end;
procedure TIEViewRulerParams.SetOnRulerGripDblClick(const Value: TRulerGripClickEvent);
begin
fHorzRuler.fOnRulerGripDblClick := Value;
fVertRuler.fOnRulerGripDblClick := Value;
end;
function TIEViewRulerParams.GetOnRulerPosChange: TRulerGripPosChangeEvent;
begin
result := fHorzRuler.fOnRulerGripPosChange;
end;
procedure TIEViewRulerParams.SetOnRulerPosChange(const Value: TRulerGripPosChangeEvent);
begin
fHorzRuler.fOnRulerGripPosChange := Value;
fVertRuler.fOnRulerGripPosChange := Value;
end;
end.