
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@44 8e941d3f-bd1b-0410-a28a-d453659cc2b4
691 lines
18 KiB
ObjectPascal
691 lines
18 KiB
ObjectPascal
{*********************************************************}
|
|
{* OVCCARET.PAS 4.06 *}
|
|
{*********************************************************}
|
|
|
|
{* ***** BEGIN LICENSE BLOCK ***** *}
|
|
{* Version: MPL 1.1 *}
|
|
{* *}
|
|
{* The contents of this file are subject to the Mozilla Public License *}
|
|
{* Version 1.1 (the "License"); you may not use this file except in *}
|
|
{* compliance with the License. You may obtain a copy of the License at *}
|
|
{* http://www.mozilla.org/MPL/ *}
|
|
{* *}
|
|
{* Software distributed under the License is distributed on an "AS IS" basis, *}
|
|
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
|
|
{* for the specific language governing rights and limitations under the *}
|
|
{* License. *}
|
|
{* *}
|
|
{* The Original Code is TurboPower Orpheus *}
|
|
{* *}
|
|
{* The Initial Developer of the Original Code is TurboPower Software *}
|
|
{* *}
|
|
{* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *}
|
|
{* TurboPower Software Inc. All Rights Reserved. *}
|
|
{* *}
|
|
{* Contributor(s): *}
|
|
{* *}
|
|
{* ***** END LICENSE BLOCK ***** *}
|
|
|
|
{$I OVC.INC}
|
|
|
|
{$B-} {Short-circuit Boolean Evaluation}
|
|
{$I+} {Input/Output-Checking}
|
|
{$P+} {Open Parameters}
|
|
{$T-} {Typed @ Operator}
|
|
{.W-} {Windows Stack Frame}
|
|
{$X+} {Extended Syntax}
|
|
|
|
unit ovccaret;
|
|
{-Caret handling class}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFNDEF LCL} Windows, {$ELSE} LclIntf, MyMisc, {$ENDIF}
|
|
Graphics, Classes, Controls, Forms;
|
|
|
|
type
|
|
TOvcCaretShape = ( {Predefined caret shapes..}
|
|
csBlock, {..block over whole cell}
|
|
csHalfBlock, {..block over bottom part of cell}
|
|
csVertLine, {..vertical line to left of cell}
|
|
csHorzLine, {..horizontal line on bottom of cell}
|
|
csCustom, {..custom width/height}
|
|
csBitmap); {..bitmap caret, custom width/height}
|
|
|
|
TOvcCaretAlign = ( {Alignment of caret in cell..}
|
|
caLeft, {..left side, centered vertically}
|
|
caTop, {..top side, centered horizontally}
|
|
caRight, {..right side, centered vertically}
|
|
caBottom, {..bottom side, centered horizontally}
|
|
caCenter); {..centered vertically and horizontally}
|
|
|
|
type
|
|
{Class defining a caret shape}
|
|
TOvcCaret = class(TPersistent)
|
|
{.Z+}
|
|
protected
|
|
{property fields}
|
|
FAlign : TOvcCaretAlign; {Caret alignment in cell}
|
|
FBitmap : TBitmap; {Bitmap for a bitmapped caret}
|
|
FBitmapX : Integer; {Bitmap's hotspot X}
|
|
FBitmapY : Integer; {Bitmap's hotspot Y}
|
|
FBlinkTime : word; {Blink time}
|
|
FCaretHt : Integer; {Height: autosized for some shapes}
|
|
FCaretWd : Integer; {Width: autosized for some shapes}
|
|
FIsGray : boolean; {True if a 'gray' caret}
|
|
FShape : TOvcCaretShape; {Shape}
|
|
|
|
FOnChange : TNotifyEvent; {Owner's change notification}
|
|
|
|
{internal fields}
|
|
RefCount : word; {Reference count}
|
|
|
|
{property access methods}
|
|
procedure SetAlign(A : TOvcCaretAlign);
|
|
procedure SetBitmap(BM : TBitMap);
|
|
procedure SetBitmapX(X : Integer);
|
|
procedure SetBitmapY(Y : Integer);
|
|
procedure SetBlinkTime(BT : word);
|
|
procedure SetCaretHeight(CH : Integer);
|
|
procedure SetCaretWidth(CW : Integer);
|
|
procedure SetIsGray(IG : boolean);
|
|
procedure SetShape(S : TOvcCaretShape);
|
|
|
|
{general methods}
|
|
procedure NotifyChange;
|
|
|
|
public
|
|
{VCL methods}
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
{other methods}
|
|
procedure Register;
|
|
procedure Deregister;
|
|
|
|
{properties}
|
|
property OnChange : TNotifyEvent
|
|
read FOnChange
|
|
write FOnChange;
|
|
{.Z-}
|
|
|
|
published
|
|
{properties}
|
|
property Bitmap : TBitmap
|
|
read FBitmap write SetBitmap;
|
|
property BitmapHotSpotX : Integer
|
|
read FBitmapX write SetBitmapX
|
|
default 0;
|
|
property BitmapHotSpotY : Integer
|
|
read FBitmapY write SetBitmapY
|
|
default 0;
|
|
property Shape : TOvcCaretShape
|
|
read FShape write SetShape
|
|
default csVertLine;
|
|
property Align : TOvcCaretAlign
|
|
read FAlign write SetAlign
|
|
default caLeft;
|
|
property BlinkTime : word
|
|
read FBlinkTime write SetBlinkTime
|
|
default 0;
|
|
property CaretHeight : Integer
|
|
read FCaretHt write SetCaretHeight
|
|
default 10;
|
|
property CaretWidth : Integer
|
|
read FCaretWd write SetCaretWidth
|
|
default 2;
|
|
property IsGray : boolean
|
|
read FIsGray write SetIsGray
|
|
default False;
|
|
end;
|
|
|
|
{.Z+}
|
|
type
|
|
TOvcSingleCaret = class(TPersistent)
|
|
{Class defining a Single caret}
|
|
protected
|
|
{property fields}
|
|
FCaretType : TOvcCaret; {Current caret type}
|
|
FHeight : Integer; {Cell height}
|
|
FLinked : boolean; {True if linked to owner}
|
|
FPos : TPoint; {Position within owner}
|
|
FVisible : boolean; {True if visible}
|
|
FWidth : Integer; {Cell width}
|
|
|
|
{other fields}
|
|
OrigBlinkTime : word; {Blink time before linking}
|
|
Owner : TWinControl; {Owning control}
|
|
XOffset : Integer; {X Offset of caret in cell}
|
|
YOffset : Integer; {Y Offset of caret in cell}
|
|
|
|
{property access methods}
|
|
procedure SetCaretType(CT : TOvcCaret);
|
|
procedure SetCellHeight(CH : Integer);
|
|
procedure SetCellWidth(CW : Integer);
|
|
procedure SetLinked(L : boolean);
|
|
procedure SetPos(P : TPoint);
|
|
procedure SetVisible(V : boolean);
|
|
|
|
{general methods}
|
|
procedure MakeShape;
|
|
procedure Reinit;
|
|
procedure ResetPos;
|
|
|
|
public
|
|
{VCL methods}
|
|
constructor Create(AOwner : TWinControl);
|
|
destructor Destroy; override;
|
|
|
|
{general methods}
|
|
procedure CaretTypeHasChanged(Sender : TObject);
|
|
|
|
{properties}
|
|
property CaretType : TOvcCaret
|
|
read FCaretType
|
|
write SetCaretType;
|
|
|
|
property CellHeight : Integer
|
|
read FHeight
|
|
write SetCellHeight;
|
|
|
|
property CellWidth : Integer
|
|
read FWidth
|
|
write SetCellWidth;
|
|
|
|
property Linked : boolean
|
|
read FLinked
|
|
write SetLinked
|
|
stored false;
|
|
|
|
property Position : TPoint
|
|
read FPos
|
|
write SetPos;
|
|
|
|
property Visible : boolean
|
|
read FVisible
|
|
write SetVisible;
|
|
end;
|
|
|
|
type
|
|
TOvcCaretPair = class(TOvcSingleCaret)
|
|
{Class defining a pair of carets, one each for insert/overwrite modes}
|
|
protected
|
|
{property fields}
|
|
FInsMode : boolean;
|
|
FInsCaretType : TOvcCaret;
|
|
FOvrCaretType : TOvcCaret;
|
|
|
|
{property access methods}
|
|
procedure SetInsMode(IM : boolean);
|
|
procedure SetInsCaretType(ICT : TOvcCaret);
|
|
procedure SetOvrCaretType(OCT : TOvcCaret);
|
|
|
|
public
|
|
{VCL methods}
|
|
constructor Create(AOwner : TWinControl);
|
|
destructor Destroy; override;
|
|
|
|
{properties}
|
|
property InsertMode : boolean
|
|
read FInsMode
|
|
write SetInsMode;
|
|
|
|
property InsCaretType : TOvcCaret
|
|
read FInsCaretType
|
|
write SetInsCaretType;
|
|
|
|
property OvrCaretType : TOvcCaret
|
|
read FOvrCaretType
|
|
write SetOvrCaretType;
|
|
end;
|
|
{.Z-}
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
{---TOvcCaret----------------------------------------------------}
|
|
constructor TOvcCaret.Create;
|
|
begin
|
|
inherited Create;
|
|
|
|
FShape := csVertLine;
|
|
FAlign := caLeft;
|
|
FBlinkTime := 0;
|
|
FIsGray := False;
|
|
FBitMap := TBitMap.Create;
|
|
FCaretHt := 10;
|
|
FCaretWd := 2;
|
|
end;
|
|
{--------}
|
|
destructor TOvcCaret.Destroy;
|
|
begin
|
|
FBitMap.Free;
|
|
inherited Destroy;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.Deregister;
|
|
begin
|
|
{decrement the reference count, if no one references us
|
|
any more, kill ourselves}
|
|
dec(RefCount);
|
|
if (RefCount = 0) then
|
|
Free;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.NotifyChange;
|
|
begin
|
|
if Assigned(FOnChange) then
|
|
FOnChange(Self);
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.Register;
|
|
begin
|
|
inc(RefCount);
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetAlign(A : TOvcCaretAlign);
|
|
begin
|
|
if (A <> FAlign) then
|
|
begin
|
|
FAlign := A;
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetBitmap(BM : TBitmap);
|
|
begin
|
|
if not Assigned(BM) then
|
|
Exit;
|
|
FBitMap.Assign(BM);
|
|
NotifyChange;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetBitmapX(X : Integer);
|
|
begin
|
|
if (X <> FBitMapX) then
|
|
begin
|
|
FBitMapX := X;
|
|
if (Shape = csBitMap) then
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetBitmapY(Y : Integer);
|
|
begin
|
|
if (Y <> FBitMapY) then
|
|
begin
|
|
FBitMapY := Y;
|
|
if (Shape = csBitMap) then
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetBlinkTime(BT : word);
|
|
begin
|
|
if (BT <> FBlinkTime) then
|
|
begin
|
|
FBlinkTime := BT;
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetCaretHeight(CH : Integer);
|
|
begin
|
|
if (CH <> FCaretHt) and (CH > 0) then
|
|
begin
|
|
FCaretHt := CH;
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetCaretWidth(CW : Integer);
|
|
begin
|
|
if (CW <> FCaretWd) and (CW > 0) then
|
|
begin
|
|
FCaretWd := CW;
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetIsGray(IG : boolean);
|
|
begin
|
|
if (IG <> FIsGray) then
|
|
begin
|
|
FIsGray := IG;
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaret.SetShape(S : TOvcCaretShape);
|
|
begin
|
|
if (S <> FShape) then
|
|
begin
|
|
FShape := S;
|
|
case FShape of
|
|
csBlock:
|
|
FAlign := caLeft;
|
|
csVertLine :
|
|
begin
|
|
FAlign := caLeft;
|
|
FCaretWd := 2;
|
|
end;
|
|
csHalfBlock:
|
|
FAlign := caBottom;
|
|
csHorzLine :
|
|
begin
|
|
FAlign := caBottom;
|
|
FCaretHt := 2;
|
|
end;
|
|
csBitmap :
|
|
begin
|
|
FCaretHt := FBitMap.Height;
|
|
FCaretWd := FBitMap.Width;
|
|
end;
|
|
end;{case}
|
|
NotifyChange;
|
|
end;
|
|
end;
|
|
{--------------------------------------------------------------------}
|
|
|
|
|
|
{---TOvcSingleCaret--------------------------------------------------}
|
|
constructor TOvcSingleCaret.Create(AOwner : TWinControl);
|
|
begin
|
|
inherited Create;
|
|
Owner := AOwner;
|
|
|
|
FHeight := 10;
|
|
FWidth := 10;
|
|
|
|
{make our default caret type}
|
|
FCaretType := TOvcCaret.Create;
|
|
FCaretType.Register;
|
|
Reinit;
|
|
end;
|
|
{--------}
|
|
destructor TOvcSingleCaret.Destroy;
|
|
begin
|
|
Visible := false;
|
|
Linked := false;
|
|
FCaretType.Deregister;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.CaretTypeHasChanged(Sender : TObject);
|
|
var
|
|
WasLinked : boolean;
|
|
begin
|
|
{if something has changed about the caret, unlink from
|
|
our owner, recalc our values, relink}
|
|
WasLinked := Linked;
|
|
Linked := false;
|
|
Reinit;
|
|
Linked := WasLinked;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.MakeShape;
|
|
begin
|
|
{don't bother if we aren't linked to anything or if we
|
|
don't have a caret type}
|
|
if (not Linked) or (not Assigned(FCaretType)) then
|
|
Exit;
|
|
|
|
{create the caret, and if necessary show it}
|
|
with FCaretType do
|
|
if (Shape = csBitmap) then
|
|
CreateCaret(Owner.Handle, Bitmap.Handle, 0, 0)
|
|
else CreateCaret(Owner.Handle, ord(IsGray), CaretWidth, CaretHeight);
|
|
if Visible then
|
|
ShowCaret(Owner.Handle);
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.Reinit;
|
|
var
|
|
NewXOfs : Integer;
|
|
NewYOfs : Integer;
|
|
begin
|
|
{don't bother if we don't have a caret type}
|
|
if (not Assigned(FCaretType)) then
|
|
Exit;
|
|
|
|
{inits}
|
|
NewXOfs := 0;
|
|
NewYOfs := 0;
|
|
|
|
with FCaretType do
|
|
begin
|
|
{stop recursion}
|
|
OnChange := nil;
|
|
|
|
{recalc the caret type's height and width}
|
|
if (Shape <> csBitmap) and (Shape <> csCustom) then
|
|
begin
|
|
case Shape of
|
|
csBlock :
|
|
begin
|
|
CaretHeight := FHeight;
|
|
CaretWidth := FWidth;
|
|
end;
|
|
csHalfBlock:
|
|
begin
|
|
CaretHeight := FHeight div 2;
|
|
CaretWidth := FWidth;
|
|
end;
|
|
csVertLine : CaretHeight := FHeight;
|
|
csHorzLine : CaretWidth := FWidth;
|
|
end;{case}
|
|
end;
|
|
|
|
{allow changes to percolate through again}
|
|
OnChange := CaretTypeHasChanged;
|
|
|
|
{recalc the X and Y offsets}
|
|
case Align of
|
|
caLeft : begin
|
|
NewXOfs := 0;
|
|
NewYOfs := (FHeight - CaretHeight) div 2;
|
|
end;
|
|
caTop : begin
|
|
NewXOfs := (FWidth - CaretWidth) div 2;
|
|
NewYOfs := 0;
|
|
end;
|
|
caRight : begin
|
|
NewXOfs := FWidth - CaretWidth;
|
|
NewYOfs := (FHeight - CaretHeight) div 2;;
|
|
end;
|
|
caBottom : begin
|
|
NewXOfs := (FWidth - CaretWidth) div 2;
|
|
NewYOfs := FHeight - CaretHeight;
|
|
end;
|
|
caCenter : begin
|
|
NewXOfs := (FWidth - CaretWidth) div 2;
|
|
NewYOfs := (FHeight - CaretHeight) div 2;
|
|
end;
|
|
end;{case}
|
|
if (Shape = csBitMap) then
|
|
begin
|
|
dec(NewXOfs, BitMapHotSpotX);
|
|
dec(NewYOfs, BitMapHotSpotY);
|
|
end;
|
|
if (NewXOfs <> XOffset) or (NewYOfs <> YOffset) then
|
|
begin
|
|
XOffset := NewXOfs;
|
|
YOffset := NewYOfs;
|
|
if Linked then
|
|
ResetPos;
|
|
end;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.ResetPos;
|
|
var
|
|
NewX, NewY : Integer;
|
|
begin
|
|
if (FPos.X = MaxInt) then
|
|
NewX := MaxInt
|
|
else NewX := FPos.X + XOffset;
|
|
if (FPos.Y = MaxInt) then
|
|
NewY := MaxInt
|
|
else NewY := FPos.Y + YOffset;
|
|
SetCaretPos(NewX, NewY);
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.SetCaretType(CT : TOvcCaret);
|
|
begin
|
|
if (CT <> FCaretType) then
|
|
begin
|
|
FCaretType.Deregister;
|
|
FCaretType := CT;
|
|
FCaretType.Register;
|
|
FCaretType.OnChange := CaretTypeHasChanged;
|
|
CaretTypeHasChanged(Self);
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.SetCellHeight(CH : Integer);
|
|
begin
|
|
if (CH <> FHeight) and (CH > 0) then
|
|
begin
|
|
FHeight := CH;
|
|
CaretTypeHasChanged(Self);
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.SetCellWidth(CW : Integer);
|
|
begin
|
|
if (CW <> FWidth) and (CW > 0) then
|
|
begin
|
|
FWidth := CW;
|
|
CaretTypeHasChanged(Self);
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.SetLinked(L : boolean);
|
|
begin
|
|
if (L <> FLinked) then
|
|
begin
|
|
FLinked := L;
|
|
if Assigned(Owner) and Owner.HandleAllocated then
|
|
if FLinked then
|
|
begin
|
|
OrigBlinkTime := GetCaretBlinkTime;
|
|
MakeShape;
|
|
ResetPos;
|
|
if (OrigBlinkTime <> CaretType.BlinkTime) then
|
|
if (CaretType.BlinkTime <> 0) then
|
|
SetCaretBlinkTime(CaretType.BlinkTime);
|
|
end
|
|
else
|
|
begin
|
|
SetCaretBlinkTime(OrigBlinkTime);
|
|
{$IFNDEF LCL}
|
|
DestroyCaret;
|
|
{$ELSE}
|
|
DestroyCaret(Owner.Handle);
|
|
{$ENDIF}
|
|
end
|
|
else
|
|
FLinked := false;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.SetPos(P : TPoint);
|
|
begin
|
|
if (P.X < 0) then
|
|
P.X := MaxInt;
|
|
if (P.Y < 0) then
|
|
P.Y := MaxInt;
|
|
if (P.X <> FPos.X) or (P.Y <> FPos.Y) then
|
|
begin
|
|
FPos := P;
|
|
if Linked then
|
|
ResetPos;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcSingleCaret.SetVisible(V : boolean);
|
|
begin
|
|
if (V <> FVisible) then
|
|
begin
|
|
FVisible := V;
|
|
if Linked then
|
|
if Owner.HandleAllocated then
|
|
if FVisible then
|
|
ShowCaret(Owner.Handle)
|
|
else
|
|
HideCaret(Owner.Handle);
|
|
end;
|
|
end;
|
|
|
|
|
|
{---TOvcCaretPair----------------------------------------------------}
|
|
constructor TOvcCaretPair.Create(AOwner : TWinControl);
|
|
begin
|
|
inherited Create(AOwner);
|
|
|
|
FInsCaretType := TOvcCaret.Create;
|
|
FInsCaretType.Register;
|
|
|
|
FOvrCaretType := TOvcCaret.Create;
|
|
FOvrCaretType.Register;
|
|
FOvrCaretType.Shape := csBlock;
|
|
|
|
FInsMode := True;
|
|
|
|
if FInsMode then
|
|
CaretType := FInsCaretType
|
|
else
|
|
CaretType := FOvrCaretType
|
|
end;
|
|
|
|
destructor TOvcCaretPair.Destroy;
|
|
begin
|
|
FInsCaretType.Deregister;
|
|
FOvrCaretType.Deregister;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TOvcCaretPair.SetInsMode(IM : boolean);
|
|
begin
|
|
if (IM <> FInsMode) then
|
|
begin
|
|
FInsMode := IM;
|
|
if FInsMode then
|
|
CaretType := FInsCaretType
|
|
else CaretType := FOvrCaretType;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaretPair.SetInsCaretType(ICT : TOvcCaret);
|
|
begin
|
|
if (ICT <> FInsCaretType) then
|
|
begin
|
|
FInsCaretType.Deregister;
|
|
FInsCaretType := ICT;
|
|
FInsCaretType.Register;
|
|
if InsertMode then
|
|
CaretType := FInsCaretType;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure TOvcCaretPair.SetOvrCaretType(OCT : TOvcCaret);
|
|
begin
|
|
if (OCT <> FOvrCaretType) then
|
|
begin
|
|
FOvrCaretType.Deregister;
|
|
FOvrCaretType := OCT;
|
|
FOvrCaretType.Register;
|
|
if not InsertMode then
|
|
CaretType := FOvrCaretType;
|
|
end;
|
|
end;
|
|
{--------------------------------------------------------------------}
|
|
|
|
|
|
end.
|