lazarus-ccr/components/industrialstuff/source/lednumber.pas
2016-12-28 18:43:45 +00:00

586 lines
18 KiB
ObjectPascal

{*********************************************************}
{* VPLEDLABEL.PAS 1.03 -> LEDNumber.PAS *}
{*********************************************************}
{* ***** 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 Visual PlanIt *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C) 2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* Modified by Jurassic Pork for include in industrial Stuff Lazarus package *}
{* 05/2013 *}
{* ***** END LICENSE BLOCK ***** *}
unit LedNumber;
{$mode objfpc}{$H+}
interface
uses
LMessages, Classes, Controls, Graphics;
type
TSegmentSize = 2..10;
TLedNumberBorderStyle = (lnbNone, lnbSingle, lnbSunken, lnbRaised);
{ TCustomLEDNumber }
TCustomLEDNumber = class(TGraphicControl)
private
FBorderStyle: TLedNumberBorderStyle;
FTransparent: boolean;
procedure SetBorderStyle(AValue: TLedNumberBorderStyle);
procedure SetTransparent(AValue: boolean);
protected{private}
FBgColor : TColor;
FOffColor : TColor;
FOnColor : TColor;
FColumns : Integer;
FRows : Integer;
FSize : TSegmentSize;
lbDrawBmp : TBitmap;
procedure CMTextChanged(var Message: TLMessage); message CM_TEXTCHANGED;
procedure Initialize(var Points: array of TPoint);
function NewOffset(xOry: char; OldOffset: Integer): Integer;
procedure ProcessCaption(Points: array of TPoint);
procedure PaintSegment(Segment: Integer; TheColor: TColor;
Points: array of TPoint; OffsetX, OffsetY: Integer);
procedure ResizeControl(Row, Col, Size: Integer);
function GetAbout: string;
procedure SetAbout(const Value: string);
procedure SetSize(Value: TSegmentSize);
procedure SetOnColor(Value: TColor);
procedure SetOffColor(Value: TColor);
procedure SetRows(Value: Integer);
procedure SetColumns(Value: Integer);
procedure SetbgColor(Value: TColor);
procedure SelectSegments(Segment: Word; Points: array of TPoint;
OffsetX, OffsetY: Integer);
protected
procedure Paint; override;
public
constructor Create(AOwner:TComponent);override;
destructor Destroy; override;
{properties}
property Version: string read GetAbout write SetAbout stored False;
property BorderStyle: TLedNumberBorderStyle read FBorderStyle write SetBorderStyle default lnbNone; {Draws border around segments.}
property Columns: Integer read FColumns write SetColumns default 10;
property Rows: Integer read FRows write SetRows default 1;
property BgColor: TColor read FbgColor write SetbgColor default clBlack;
property OffColor: TColor read FOffColor write SetOffColor default $000E3432;
property OnColor: TColor read FOnColor write SetOnColor default clLime;
property Size: TSegmentSize read FSize write SetSize default 2;
property Transparent: boolean read FTransparent write SetTransparent default false; {Draws segments with transparent background.BgColor is used as mask color.}
{Inherited properties}
property Caption;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
end;
TLEDNumber = class(TCustomLEDNumber)
published
property Version;
property BorderStyle;
property Caption;
property Columns;
property Rows;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property BgColor;
property OffColor;
property OnColor;
property ParentShowHint;
property PopupMenu;
property Size;
property ShowHint;
property Transparent;
property Visible;
end;
implementation
// uses
// VpConst;
{ LED Segment Map }
{ }
{ ------------------------ }
{ | 1 | }
{ ------------------------ }
{ | | \ | | / | | }
{ | | \ | | / | | }
{ | | \ | | / | | }
{ |2 |\3 \ |4 | /5 /|6 | }
{ | | \ \| |/ / | | }
{ | | \ | | / | | }
{ ----------- ----------- }
{ | 7 \/ 8 | }
{ -----------/\----------- }
{ | | / | | \ | | }
{ | | / /| |\ \ | | }
{ |9 |/10 / |11| \12 \|13| }
{ | | / | | \ | | }
{ | | / | | \ | | }
{ | | / | | \ | | }
{ ------------------------ |-----| }
{ | 14 | | * | }
{ ------------------------ |-----| }
{ }
{ * Period and comma are drawn here }
{ Colon is drawn in the center of }
{ segments 4 and 11 }
{ Each segment is made up of 6 points. The segments that don't need 6 points, }
{ such as the period and colon dots, return to the coordinates of the initial }
{ point for the remaining unused points. }
const
{LED SEGMENT ARRAYS}
MAX_POINTS = 107;
DigitPoints: array[0..MAX_POINTS] of TPoint =
{Segment 1}
((X:2;Y:2),(X:3;Y:1),(X:11;Y:1),(X:12;Y:2),(X:11;Y:3),(X:3;Y:3),
{Segment 2}
(X:2;Y:3),(X:3;Y:4),(X:3;Y:12),(X:2;Y:13),(X:1;Y:12),(X:1;Y:4),
{Segment 3}
(X:3;Y:3),(X:6;Y:9),(X:6;Y:13),(X:3;Y:7),(X:3;Y:3),(X:3;Y:3),
{Segment 4}
(X:7;Y:3),(X:8;Y:4),(X:8;Y:12),(X:7;Y:13),(X:6;Y:12),(X:6;Y:4),
{Segment 5}
(X:11;Y:3),(X:11;Y:7),(X:8;Y:13),(X:8;Y:9),(X:11;Y:3),(X:11;Y:3),
{Segment 6}
(X:12;Y:3),(X:13;Y:4),(X:13;Y:12),(X:12;Y:13),(X:11;Y:12),(X:11;Y:4),
{Segment 7}
(X:2;Y:14),(X:3;Y:13),(X:6;Y:13),(X:7;Y:14),(X:6;Y:15),(X:3;Y:15),
{Segment 8}
(X:7;Y:14),(X:8;Y:13),(X:11;Y:13),(X:12;Y:14),(X:11;Y:15),(X:8;Y:15),
{Segment 9}
(X:2;Y:15),(X:3;Y:16),(X:3;Y:24),(X:2;Y:25),(X:1;Y:24),(X:1;Y:16),
{Segment 10}
(X:6;Y:15),(X:6;Y:19),(X:3;Y:25),(X:3;Y:21),(X:6;Y:15),(X:6;Y:15),
{Segment 11}
(X:7;Y:15),(X:8;Y:16),(X:8;Y:24),(X:7;Y:25),(X:6;Y:24),(X:6;Y:16),
{Segment 12}
(X:8;Y:15),(X:11;Y:21),(X:11;Y:25),(X:8;Y:19),(X:8;Y:15),(X:8;Y:15),
{Segment 13}
(X:12;Y:15),(X:13;Y:16),(X:13;Y:24),(X:12;Y:25),(X:11;Y:24),(X:11;Y:16),
{Segment 14}
(X:2;Y:26),(X:3;Y:25),(X:11;Y:25),(X:12;Y:26),(X:11;Y:27),(X:3;Y:27),
{Period }
(X:14;Y:25),(X:16;Y:25),(X:16;Y:27),(X:14;Y:27),(X:14;Y:25),(X:14;Y:25),
{Comma }
(X:14;Y:25),(X:16;Y:25),(X:16;Y:27),(X:13;Y:30),(X:14;Y:27),(X:14;Y:25),
{Colon Top }
(X:5;Y:7),(X:9;Y:7),(X:9;Y:10),(X:5;Y:10),(X:5;Y:7),(X:5;Y:7),
{Colon Btm }
(X:5;Y:20),(X:9;Y:20),(X:9;Y:23),(X:5;Y:23),(X:5;Y:20),(X:5;Y:20));
Characters: Array[0..72] of Word =
($0000,$3B70,$1320,$0001,$0300,$0002,$0840,$CCCC,$1020,$8784,
{ ' ' * + , - . / 0 1 2 }
$870C,$4708,$C30C,$C38C,$8408,$C78C,$C70C,$0810,$2040,$C788,
{ 3 4 5 6 7 8 9 < > A }
$952C,$C084,$942C,$C384,$C380,$C18C,$4788,$9024,$048C,$4A90,
{ B C D E F G H I J K }
$4084,$6C88,$6498,$C48C,$C780,$C49E,$C790,$C214,$9020,$448C,
{ L M N O P Q R S T U }
$48C0,$44D8,$2850,$2820,$8844,$2010,$C788,$952C,$C084,$942C,
{ V W X Y Z / a b c d }
$C384,$C380,$C18C,$4788,$9024,$048C,$4A90,$4084,$6C88,$6498,
{ e f g h i j k l m n }
$C48C,$C780,$C49E,$C790,$C214,$9020,$448C,$48C0,$44D8,$2850,
{ o p q r s t u v w x }
$2820,$8844,$FFFF);
{ y z : }
CharacterNDX: Array[1..122] of integer =
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 72, 0, 17, 0, 18, 0, 0, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 0, 45, 0, 0, 0, 0, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44);
{===== TCustomLEDNumber ============================================}
constructor TCustomLEDNumber.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
FTransparent := False;
FBorderStyle := lnbNone;
ControlStyle := [csCaptureMouse,
csOpaque,
csSetCaption,
csClickEvents,
csDoubleClicks];
Width := 170;
Height := 30;
FOnColor := clLime;
FOffColor := $000E3432;
FBgColor := clBlack;
FSize := 2;
FRows := 1;
FColumns := 10;
Caption := 'LED-LABEL';
lbDrawBmp := TBitmap.Create;
end;
{=====}
destructor TCustomLEDNumber.Destroy;
begin
lbDrawBmp.Free;
lbDrawBmp := nil;
inherited Destroy;
end;
{=====}
function TCustomLEDNumber.GetAbout : string;
begin
Result := ''; //VpVersionStr;
end;
{=====}
procedure TCustomLEDNumber.SetAbout(const Value : string);
begin
{Leave empty}
end;
{=====}
procedure TCustomLEDNumber.SetTransparent(AValue: boolean);
begin
if FTransparent=AValue then Exit;
FTransparent:=AValue;
lbDrawBmp.Transparent := FTransparent;
lbDrawBmp.TransparentColor := FBgColor;
Invalidate;
end;
procedure TCustomLEDNumber.SetBorderStyle(AValue: TLedNumberBorderStyle);
begin
if FBorderStyle=AValue then Exit;
FBorderStyle:=AValue;
Invalidate;
end;
procedure TCustomLEDNumber.CMTextChanged(var Message: TLMessage);
begin
inherited;
Invalidate;
end;
{=====}
procedure TCustomLEDNumber.Initialize(var Points: array of TPoint);
var
I : Integer;
begin
for I := 0 to MAX_POINTS do begin
Points[i].X := DigitPoints[i].X * (FSize - 1);
Points[i].Y := DigitPoints[i].Y * (FSize - 1);
end;
end;
{=====}
function TCustomLEDNumber.NewOffset(xOry: char; OldOffset: Integer): Integer;
begin
if (xOry = 'x')then
newOffset := oldOffset + 17 * (FSize - 1)
else
newOffset := oldOffset + 30 * (FSize -1)
end;
{=====}
procedure TCustomLEDNumber.Paint;
var
Points: array[0..MAX_POINTS] of TPoint;
ARect: TRect;
begin
lbDrawBMP.Width := Width;
lbDrawBMP.Height := Height;
Initialize(Points);
lbDrawBMP.Canvas.Brush.Color := FBgColor;
lbDrawBMP.Canvas.FillRect(ClientRect);
ProcessCaption(Points);
Canvas.CopyMode := cmSrcCopy;
if BorderStyle <> lnbNone then
begin
ARect := ClientRect;
case BorderStyle of
lnbSingle:
begin
Canvas.Pen.Color := cl3DDkShadow;
Canvas.Frame(ARect);
end;
lnbSunken: Canvas.Frame3D(ARect, cl3DDkShadow, clBtnHiLight, 1);
lnbRaised: Canvas.Frame3D(ARect, clBtnHiLight, cl3DDkShadow, 1);
end;
inc(ARect.Left, 1);
inc(ARect.Top, 1);
inc(ARect.Right, 1);
inc(ARect.Bottom, 1);
Canvas.StretchDraw(ARect, lbDrawBMP);
end else
Canvas.Draw(0, 0, lbDrawBMP);
end;
{=====}
procedure TCustomLEDNumber.PaintSegment(Segment: Integer; TheColor: TColor;
Points: array of TPoint; OffsetX, OffsetY: Integer);
var
I: Integer;
DrawPts: array[0..5] of TPoint;
begin
Dec(Segment);
lbDrawBMP.Canvas.Pen.Style := psClear;
lbDrawBMP.Canvas.Brush.Color := TheColor;
for i := 0 to 5 do begin
DrawPts[i].X := offsetX + Points[Segment * 6 + i].X;
DrawPts[i].Y := offsetY + Points[Segment * 6 + i].Y;
end;
lbDrawBMP.Canvas.Polygon(DrawPts);
end;
{=====}
procedure TCustomLEDNumber.SelectSegments(Segment: Word;
Points: array of TPoint; OffsetX, OffsetY: Integer);
var
I : integer;
Bit : word;
MyColor : TColor;
Skip : Boolean;
begin
if (Segment and $FFFF) = $FFFF then begin
MyColor := FOnColor;
PaintSegment(17, MyColor, Points, OffsetX, OffsetY);
PaintSegment(18, MyColor, Points, OffsetX, OffsetY);
end
else begin
Bit := $8000;
for I := 1 to 16 do begin
Skip := False;
if (Segment and Bit) = Bit then
MyColor := FOnColor
else begin
if (i = 15) or (i = 16) then
Skip := True;
MyColor := FOffColor;
end;
if (not Skip) and (MyColor <> FBgColor) then
PaintSegment(I, MyColor, Points, OffsetX, OffsetY);
Bit := Bit div 2;
end;
end;
end;
{=====}
procedure TCustomLEDNumber.ProcessCaption(Points: array of TPoint);
var
Next : Char;
Last : Char;
I, X : Integer;
Row, ColsPerRow: Integer;
Tmp : Integer;
OffsetX : Integer;
OffsetY : Integer;
DisplayStr : string;
begin
Last := #0;
OffsetX := FSize;
OffsetY := 0;
DisplayStr := Caption;
if Length(DisplayStr) > 0 then
if (DisplayStr[1] = ',') or (DisplayStr[1] = '.') then
DisplayStr := ' ' + DisplayStr;
Row := 1;
ColsPerRow := 0;
for I := 1 to Length(Caption) do begin
Next := Caption[I];
case Ord(Next) of
42..58,60,62,65..90,92,97..122: begin
if ColsPerRow = FColumns then begin
Row := Row + 1;
if Row > FRows then
exit;
offsetY := newOffset('y',offsetY);
offsetX := FSize;
ColsPerRow := 0
end;
if (Next = '.') or (Next = ',') then
if (Last = '.') or (Last = ',') then begin
SelectSegments(Characters[CharacterNDX[Ord(Next)]], Points,
OffsetX, OffsetY);
OffsetX := NewOffset('x', OffsetX);
end
else begin
OffsetX := OffsetX - (17 * (FSize - 1));
Tmp := (Characters[CharacterNDX[Ord(Next)]]
or Characters[CharacterNDX[Ord(Last)]]);
SelectSegments(Tmp, Points, OffsetX, OffsetY);
OffsetX := NewOffset('x', OffsetX);
end
else begin
SelectSegments(Characters[CharacterNDX[Ord(Next)]], Points, OffsetX,
OffsetY);
offsetX := NewOffset('x', OffsetX);
ColsPerRow := ColsPerRow + 1;
end;
end;
10: begin {eat linefeed}
end;
13: begin
if ColsPerRow < FColumns then
for x := 1 to (FColumns - ColsPerRow) do begin
SelectSegments(Characters[CharacterNDX[1]], Points, OffsetX, OffsetY);
OffsetX := NewOffset('x', OffsetX);
end;
Row := Row + 1;
if Row > FRows then
exit;
OffsetY := NewOffset('y', OffsetY);
OffsetX := FSize;
ColsPerRow := 0;
end;
else begin
if ColsPerRow = FColumns then begin
Row := Row + 1;
if Row > FRows then
Exit;
OffsetY := NewOffset('y', OffsetY);
OffsetX := FSize;
ColsPerRow := 0;
end;
SelectSegments(Characters[CharacterNDX[1]], Points, OffsetX, OffsetY);
OffsetX := newOffset('x', OffsetX);
ColsPerRow := ColsPerRow + 1;
end;
end;
Last := Next;
end;
for x := 1 to (FColumns - ColsPerRow) do begin
SelectSegments(Characters[CharacterNDX[1]], Points, OffsetX, OffsetY);
OffsetX := NewOffset('x', OffsetX);
end;
if (FColumns * FRows) > Length(caption) then begin
for X := Row + 1 to FRows do begin
OffsetX := FSize;
OffsetY := NewOffset('y', OffsetY);
for I := 1 to FColumns do begin
SelectSegments(Characters[CharacterNDX[1]], Points, OffsetX, OffsetY);
OffsetX := NewOffset('x', OffsetX);
end;
end;
end;
end;
{=====}
procedure TCustomLEDNumber.ResizeControl(Row, Col, Size: Integer);
begin
FRows := Row;
FColumns := Col;
FSize := Size;
SetBounds(Left, Top, FColumns * 17 * (FSize - 1), FRows * 30 * (FSize - 1));
Invalidate;
end;
{=====}
procedure TCustomLEDNumber.SetbgColor(Value: TColor);
begin
if FBgColor <> Value then begin
FBgColor := Value;
Invalidate;
end;
end;
{=====}
procedure TCustomLEDNumber.SetOnColor(Value:TColor);
begin
if FOnColor <> Value then begin
FOnColor := Value;
Invalidate;
end;
end;
{=====}
procedure TCustomLEDNumber.SetOffColor(Value:TColor);
begin
if FOffColor <> Value then begin
FOffColor := Value;
Invalidate;
end;
end;
{=====}
procedure TCustomLEDNumber.SetRows(Value : Integer);
begin
if FRows <> Value then begin
if Value < 1 then
Value := 1;
ResizeControl(Value, FColumns, FSize);
end;
end;
{=====}
procedure TCustomLEDNumber.SetColumns(Value : Integer);
begin
if FColumns <> Value then begin
if Value < 1 then
Value := 1;
ResizeControl(FRows, Value, FSize);
end;
end;
{=====}
procedure TCustomLEDNumber.SetSize(Value : TSegmentSize);
begin
if FSize <> Value then begin
//if Value < 2 then <- unreachable
// Value := 2;
//if Value > 10 then
// Value := 10;
ResizeControl(FRows, FColumns, Value);
end;
end;
{=====}
end.