lazarus-ccr/components/orpheus/ovcrlbl.pas
2007-06-30 18:40:18 +00:00

521 lines
14 KiB
ObjectPascal

{*********************************************************}
{* OVCRLBL.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-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{.W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
unit ovcrlbl;
{-Rotated label component}
interface
uses
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, LclType, MyMisc, {$ENDIF}
Classes, Controls, Graphics, SysUtils,
OvcBase, OvcMisc;
type
TOvcCustomRotatedLabel = class(TOvcGraphicControl)
{.Z+}
protected {private}
{property instance variables}
FAlignment : TAlignment;
FAutoSize : Boolean;
FCaption : string;
FFontAngle : Integer;
FOriginX : Integer;
FOriginY : Integer;
FShadowColor : TColor; {color for text shadowing}
FShadowedText : Boolean; {true to draw shadowed text}
{internal variables}
rlBusy : Boolean;
{property methods}
function GetTransparent : Boolean;
procedure SetAlignment(Value : TAlignment);
procedure SetAutoSize(Value : Boolean); {$IFDEF VERSION6}{$IFNDEF LCL} override;{$ENDIF}{$ENDIF}
procedure SetCaption(const Value : string);
procedure SetOriginX(Value : Integer);
procedure SetOriginY(Value : Integer);
procedure SetShadowColor(const Value : TColor);
procedure SetShadowedText(Value : Boolean);
procedure SetTransparent(Value : Boolean);
procedure SetFontAngle(Value : Integer);
{internal methods}
procedure lblAdjustSize;
{-adjust horizontal and/or vertical size of control}
procedure lblDrawText(var R : TRect; Flags : Word);
{-draw the label text}
{VCL message handling methods}
procedure CMFontChanged(var Msg : TMessage);
message CM_FONTCHANGED;
procedure CMTextChanged(var Mes : TMessage);
message CM_TEXTCHANGED;
protected
procedure Loaded;
override;
procedure Paint;
override;
procedure SetName(const NewName : TComponentName);
override;
{.Z-}
property Alignment : TAlignment
read FAlignment write SetAlignment;
property AutoSize : Boolean
read FAutoSize write SetAutoSize;
property Caption : string
read FCaption write SetCaption;
property FontAngle : Integer
read FFontAngle write SetFontAngle;
property OriginX : Integer
read FOriginX write SetOriginX;
property OriginY : Integer
read FOriginY write SetOriginY;
property ShadowColor : TColor
read FShadowColor write SetShadowColor;
property ShadowedText : Boolean
read FShadowedText write SetShadowedText;
property Transparent : Boolean
read GetTransparent write SetTransparent;
public
{.Z+}
constructor Create(AOwner: TComponent);
override;
{.Z-}
{public properties}
property Canvas;
end;
TOvcRotatedLabel = class(TOvcCustomRotatedLabel)
published
{$IFDEF VERSION4}
property Anchors;
property Constraints;
property DragKind;
{$ENDIF}
property Align;
property Alignment default taLeftJustify;
property AutoSize;
property Caption;
property Color;
property DragCursor;
property DragMode;
property Enabled;
property Font;
property FontAngle default 0;
property Height default 20;
property OriginX default 0;
property OriginY default 0;
property ParentColor;
{property ParentFont;}
property ParentShowHint;
property PopupMenu;
property ShadowColor default clBtnShadow;
property ShadowedText;
property ShowHint;
property Transparent default False;
property Visible;
{events}
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDrag;
end;
implementation
{*** TOvcCustomRotatedLabel ***}
procedure TOvcCustomRotatedLabel.CMFontChanged(var Msg : TMessage);
var
TM : TTextMetric;
begin
inherited;
if csLoading in ComponentState then
Exit;
if FFontAngle <> 0 then begin
{check if the current font can be rotated}
Canvas.Font := Self.Font;
GetTextMetrics(Canvas.Handle, TM);
if (TM.tmPitchAndFamily and TMPF_TRUETYPE) = 0 then
{force zero font angle}
FontAngle := 0;
end;
lblAdjustSize;
end;
procedure TOvcCustomRotatedLabel.CMTextChanged(var Mes : TMessage);
begin
lblAdjustSize;
end;
constructor TOvcCustomRotatedLabel.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csReplicatable, csOpaque];
{default property values}
FAlignment := taLeftJustify;
FFontAngle := 0;
FOriginX := 0;
FOriginY := 0;
FShadowColor := clBtnShadow;
FShadowedText := False;
{$IFDEF MSWINDOWS}
Font.Name := 'Arial';
{$ELSE}
Font.Name := 'default';
{$ENDIF}
Height := 20;
Width := 130;
if csDesigning in ComponentState then
lblAdjustSize;
end;
function TOvcCustomRotatedLabel.GetTransparent : Boolean;
begin
Result := not (csOpaque in ControlStyle);
end;
procedure TOvcCustomRotatedLabel.lblAdjustSize;
{-adjust horizontal and/or vertical size of control}
var
R : TRect;
W, H, X, Y : Integer;
begin
if rlBusy then {avoid reentrance}
Exit;
rlBusy := True;
try
if not (csLoading in ComponentState) and AutoSize then begin
R := ClientRect;
Canvas.Font := Font;
W := Canvas.TextWidth(Caption);
H := Canvas.TextHeight(Caption);
if FFontAngle <> 0 then begin
{adjust height and width as necessary}
{width (X) of text at new angle}
X := Round(W * Cos(FFontAngle*Pi/180));
{height (y) of text at new angle}
Y := Round(W * Sin(FFontAngle*Pi/180));
R.Bottom := Abs(Y) + 2*H;
R.Right := Abs(X) + 2*H;
if X < 0 then
FOriginX := R.Right-H
else
FOriginX := H;
if Y < 0 then
FOriginY := H
else begin
if X < 0 then
FOriginY := R.Bottom - H
else
FOriginY := R.Bottom - H - H div 2;
end;
end else begin
FOriginX := 0;
FOriginY := 0;
R.Right := W;
R.Bottom := H;
end;
SetBounds(Left, Top, R.Right, R.Bottom);
end;
finally
rlBusy := False;
end;
end;
procedure TOvcCustomRotatedLabel.lblDrawText(var R : TRect; Flags : Word);
{-paint the controls display or calculate a TRect to fit text}
var
HoldColor : TColor;
T : string;
XO, YO : Integer;
A : Integer;
Buf : array[0..255] of Char;
{$IFDEF LCL}
FontHand : hFont;
{$ENDIF}
begin
T := Caption;
if (Flags and DT_CALCRECT <> 0) and (T = '') then
T := ' ';
Flags := Flags or DT_NOPREFIX;
{use our font}
Canvas.Font := Font;
{create the rotated font}
if FFontAngle <> 0 then
{$IFNDEF LCL}
Canvas.Font.Handle := CreateRotatedFont(Font, FFontAngle);
{$ELSE} //Workaround for now - Qt widgetset not setting Handle?
FontHand := CreateRotatedFont(Font, FFontAngle);
{$ENDIF}
{force disabled text color, if not enabled}
if not Enabled then
Canvas.Font.Color := clGrayText;
{draw the text}
StrPLCopy(Buf, T, 255);
if FFontAngle = 0 then begin
{draw shadow first, if selected}
if FShadowedText then begin
HoldColor := Canvas.Font.Color;
Canvas.Font.Color := FShadowColor;
if not Transparent then begin
SetBkMode(Canvas.Handle, OPAQUE);
Canvas.Brush.Color := Color;
end;
OffsetRect(R, +2, +1);
DrawText(Canvas.Handle, @Buf, -1, R, Flags);
Canvas.Font.Color := HoldColor;
{$IFNDEF LCL}
SetBkMode(Canvas.Handle, Windows.TRANSPARENT);
{$ELSE}
SetBkMode(Canvas.Handle, LclType.TRANSPARENT);
{$ENDIF}
OffsetRect(R, -2, -1);
DrawText(Canvas.Handle, @Buf, -1, R, Flags);
end else begin
DrawText(Canvas.Handle, @Buf, -1, R, Flags)
end;
end else begin
if FShadowedText then begin
HoldColor := Canvas.Font.Color;
Canvas.Font.Color := FShadowColor;
if not Transparent then begin
{$IFNDEF LCL}
SetBkMode(Canvas.Handle, Windows.OPAQUE);
{$ELSE}
SetBkMode(Canvas.Handle, LclType.OPAQUE);
{$ENDIF}
Canvas.Brush.Color := Color;
end;
{calculate the shadow offset based on the quadrant the text is in}
{ | } { 1 -- X+2, Y+1}
{ 2 | 1 } { 2 -- X-1, Y-2}
{ -------+--------- } { 3 -- X+2, Y+1}
{ 3 | 4 } { 4 -- X-1, Y-2}
{ | }
A := FFontAngle;
if A < 0 then A := 360 + A;
if A >= 270 then begin
XO := 2; YO := 1; {Quad=4}
end else if A >= 180 then begin
XO := 2; YO := 1; {Quad=3}
end else if A >= 90 then begin
XO := 2; YO := 1; {Quad=2}
end else begin
XO := 2; YO := 1; {Quad=1}
end;
{$IFDEF LCL}
SelectObject(Canvas.Handle, FontHand);
{$ENDIF}
ExtTextOut(Canvas.Handle, OriginX+XO, OriginY+YO, ETO_CLIPPED,
@R, Buf, StrLen(Buf), nil);
Canvas.Font.Color := HoldColor;
{$IFNDEF LCL}
SetBkMode(Canvas.Handle, Windows.TRANSPARENT);
{$ELSE}
SetBkMode(Canvas.Handle, LclType.TRANSPARENT);
{$ENDIF}
{$IFDEF LCL}
SelectObject(Canvas.Handle, FontHand);
{$ENDIF}
ExtTextOut(Canvas.Handle, OriginX, OriginY, ETO_CLIPPED,
@R, Buf, StrLen(Buf), nil);
end else begin
{$IFDEF LCL}
SelectObject(Canvas.Handle, FontHand);
{$ENDIF}
ExtTextOut(Canvas.Handle, OriginX, OriginY, ETO_CLIPPED,
@R, Buf, StrLen(Buf), nil);
end;
end;
end;
procedure TOvcCustomRotatedLabel.Loaded;
begin
inherited Loaded;
lblAdjustSize;
end;
procedure TOvcCustomRotatedLabel.Paint;
const
Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
var
R : TRect;
begin
R := ClientRect;
with Canvas do begin
if not Transparent then begin
Brush.Color := Self.Color;
Brush.Style := bsSolid;
FillRect(R);
end;
Brush.Style := bsClear;
lblDrawText(R, Alignments[FAlignment])
end;
end;
procedure TOvcCustomRotatedLabel.SetAlignment(Value : TAlignment);
begin
if FAlignment <> Value then begin
FAlignment := Value;
Invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetAutoSize(Value : Boolean);
begin
if Value <> FAutoSize then begin
FAutoSize := Value;
lblAdjustSize;
end;
end;
procedure TOvcCustomRotatedLabel.SetCaption(const Value : string);
begin
if Value <> FCaption then begin
FCaption := Value;
lblAdjustSize;
Repaint;
end;
end;
procedure TOvcCustomRotatedLabel.SetOriginX(Value : Integer);
begin
if Value <> FOriginX then begin
FOriginX := Value;
Invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetOriginY(Value : Integer);
begin
if Value <> FOriginY then begin
FOriginY := Value;
Invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetShadowColor(const Value : TColor);
begin
if Value <> FShadowColor then begin
FShadowColor := Value;
invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetShadowedText(Value : Boolean);
begin
if Value <> FShadowedText then begin
FShadowedText := Value;
Invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetTransparent(Value : Boolean);
begin
if Transparent <> Value then begin
if Value then
ControlStyle := ControlStyle - [csOpaque]
else
ControlStyle := ControlStyle + [csOpaque];
Invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetFontAngle(Value : Integer);
var
Neg : Integer;
TM : TTextMetric;
begin
if Value <> FFontAngle then begin
{check if the current font can be rotated}
if not (csLoading in ComponentState) then begin
if Value <> 0 then begin
Canvas.Font := Font;
GetTextMetrics(Canvas.Handle, TM);
if (TM.tmPitchAndFamily and TMPF_TRUETYPE) = 0 then
{force true-type font}
{$IFDEF MSWINDOWS}
Font.Name := 'Arial';
{$ENDIF}
end;
end;
if Value < 0 then Neg := -1 else Neg := 1;
FFontAngle := (Abs(Value) mod 360) * Neg;
lblAdjustSize;
{repaint with new font}
Invalidate;
end;
end;
procedure TOvcCustomRotatedLabel.SetName(const NewName : TComponentName);
begin
inherited SetName(NewName);
if (csDesigning in ComponentState) and (FCaption = '') then
FCaption := Self.Name;
end;
end.