git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jvcl@19 7f62d464-2af8-f54e-996c-e91b33f51cbe
2274 lines
71 KiB
ObjectPascal
2274 lines
71 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
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/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvSegmentedLEDDisplay.pas, released on --.
|
|
|
|
The Initial Developer of the Original Code is Marcel Bestebroer
|
|
Portions created by Marcel Bestebroer are Copyright (C) 2002 - 2003 Marcel
|
|
Bestebroer
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
Jay Dubal
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.delphi-jedi.org
|
|
|
|
Known Issues:
|
|
* Automatic unlit color calculation is not working properly. Maybe a function in JclGraphUtil
|
|
can help out there.
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvSegmentedLEDDisplay.pas 12461 2009-08-14 17:21:33Z obones $
|
|
|
|
unit JvSegmentedLEDDisplay;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$IFDEF MSWINDOWS}
|
|
Windows,
|
|
{$ENDIF MSWINDOWS}
|
|
Classes, Graphics,
|
|
JclBase,
|
|
JvComponent, JvTypes;
|
|
|
|
// Additional color values for unlit color settings (TUnlitColor type)
|
|
// asn: does this work with clx/linux?
|
|
const
|
|
clDefaultBackground = TColor($20100001);
|
|
clDefaultLitColor = TColor($20100002);
|
|
NullHandle = 0;
|
|
|
|
type
|
|
TJvCustomSegmentedLEDDisplay = class;
|
|
TJvSegmentedLEDDigits = class;
|
|
TJvCustomSegmentedLEDDigit = class;
|
|
TJvSegmentedLEDCharacterMapper = class;
|
|
|
|
TJvSegmentedLEDDigitClass = class of TJvCustomSegmentedLEDDigit;
|
|
|
|
TJvSegmentedLEDDigitClassName = type string;
|
|
TUnlitColor = type TColor;
|
|
TSlantAngle = 0 .. 44;
|
|
TSLDHitInfo = (shiNowhere, shiDigit, shiDigitSegment, shiClientArea);
|
|
{$IFNDEF RTL200_UP}
|
|
TCharSet = set of Char;
|
|
{$ENDIF ~RTL200_UP}
|
|
TSegCharMapHeader = record
|
|
ID: array[0..11] of AnsiChar;
|
|
MappedChars: TCharSet;
|
|
Flags: Longint;
|
|
end;
|
|
|
|
TSegmentRenderType = (srtNone, srtPolygon, srtRect, srtCircle);
|
|
TPointArray = array of TPoint;
|
|
|
|
TSegmentRenderInfo = record
|
|
RenderType: TSegmentRenderType;
|
|
Points: TPointArray;
|
|
end;
|
|
TSegmentRenderInfoArray = array of TSegmentRenderInfo;
|
|
|
|
EJVCLSegmentedLEDException = class(EJVCLException);
|
|
|
|
TJvCustomSegmentedLEDDisplay = class(TJvGraphicControl)
|
|
private
|
|
FCharacterMapper: TJvSegmentedLEDCharacterMapper;
|
|
FDigitClass: TJvSegmentedLEDDigitClass;
|
|
FDigits: TJvSegmentedLEDDigits;
|
|
FDotSize: Integer;
|
|
FDigitHeight: Integer;
|
|
FDigitSpacing: Integer;
|
|
FDigitWidth: Integer;
|
|
FMaxBaseTop: Integer;
|
|
FSegmentLitColor: TColor;
|
|
FSegmentSpacing: Integer;
|
|
FSegmentThickness: Integer;
|
|
FSegmentUnlitColor: TUnlitColor;
|
|
FSlant: TSlantAngle;
|
|
FText: string;
|
|
protected
|
|
procedure DefineProperties(Filer: TFiler); override;
|
|
procedure Loaded; override;
|
|
procedure Paint; override;
|
|
function GetText: string;
|
|
procedure SetText(Value: string);
|
|
procedure SetDigitHeight(Value: Integer);
|
|
procedure SetDigits(Value: TJvSegmentedLEDDigits);
|
|
procedure SetDigitSpacing(Value: Integer);
|
|
procedure SetDigitWidth(Value: Integer);
|
|
procedure SetDigitClass(Value: TJvSegmentedLEDDigitClass);
|
|
procedure SetDotSize(Value: Integer);
|
|
procedure SetSegmentLitColor(Value: TColor);
|
|
procedure SetSegmentSpacing(Value: Integer);
|
|
procedure SetSegmentThickness(Value: Integer);
|
|
procedure SetSegmentUnlitColor(Value: TUnlitColor);
|
|
procedure SetSlant(Value: TSlantAngle);
|
|
function GetDigitClassName: TJvSegmentedLEDDigitClassName;
|
|
procedure SetDigitClassName(Value: TJvSegmentedLEDDigitClassName);
|
|
function GetRealUnlitColor: TColor;
|
|
function CalcRealUnlitColorBackground: TColor;
|
|
function CalcRealUnlitColorLitColor: TColor;
|
|
procedure PrimSetText(Value: string);
|
|
procedure BaseTopChanged;
|
|
procedure HeightChanged;
|
|
procedure UpdateDigitsPositions;
|
|
procedure InvalidateDigits;
|
|
procedure InvalidateView;
|
|
procedure UpdateText;
|
|
procedure UpdateBounds;
|
|
property AutoSize default True;
|
|
property CharacterMapper: TJvSegmentedLEDCharacterMapper read FCharacterMapper;
|
|
property DigitClass: TJvSegmentedLEDDigitClass read FDigitClass write SetDigitClass;
|
|
// Solely needed for design time support of DigitClass
|
|
property DigitClassName: TJvSegmentedLEDDigitClassName read GetDigitClassName write SetDigitClassName;
|
|
property DigitHeight: Integer read FDigitHeight write SetDigitHeight default 30;
|
|
property Digits: TJvSegmentedLEDDigits read FDigits write SetDigits;
|
|
property DigitSpacing: Integer read FDigitSpacing write SetDigitSpacing default 2;
|
|
property DigitWidth: Integer read FDigitWidth write SetDigitWidth default 20;
|
|
property DotSize: Integer read FDotSize write SetDotSize default 4;
|
|
property SegmentLitColor: TColor read FSegmentLitColor write SetSegmentLitColor default clWindowText;
|
|
property SegmentSpacing: Integer read FSegmentSpacing write SetSegmentSpacing default 2;
|
|
property SegmentThickness: Integer read FSegmentThickness write SetSegmentThickness default 2;
|
|
property SegmentUnlitColor: TUnlitColor read FSegmentUnlitColor write SetSegmentUnlitColor default clDefaultLitColor;
|
|
property Slant: TSlantAngle read FSlant write SetSlant default 0;
|
|
property Text: string read GetText write SetText;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure RemapText;
|
|
function GetHitInfo(X, Y: Integer): TSLDHitInfo; overload;
|
|
function GetHitInfo(X, Y: Integer; out Digit: TJvCustomSegmentedLEDDigit;
|
|
out SegmentIndex: Integer): TSLDHitInfo; overload;
|
|
end;
|
|
|
|
TJvSegmentedLEDDisplay = class(TJvCustomSegmentedLEDDisplay)
|
|
public
|
|
property DigitClass;
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property AutoSize;
|
|
property Color;
|
|
property DigitClassName;
|
|
property DigitHeight;
|
|
property Digits;
|
|
property DigitSpacing;
|
|
property DigitWidth;
|
|
property DotSize;
|
|
property ParentColor;
|
|
property PopupMenu;
|
|
property SegmentLitColor;
|
|
property SegmentSpacing;
|
|
property SegmentThickness;
|
|
property SegmentUnlitColor;
|
|
property Slant;
|
|
property Text;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
end;
|
|
|
|
TJvSegmentedLEDDigits = class(TOwnedCollection)
|
|
protected
|
|
function GetItem(Index: Integer): TJvCustomSegmentedLEDDigit;
|
|
procedure SetItem(Index: Integer; Value: TJvCustomSegmentedLEDDigit);
|
|
function Display: TJvCustomSegmentedLEDDisplay;
|
|
procedure Update(Item: TCollectionItem); override;
|
|
public
|
|
constructor Create(AOwner: TPersistent);
|
|
property Items[Index: Integer]: TJvCustomSegmentedLEDDigit read GetItem write SetItem; default;
|
|
end;
|
|
|
|
TJvCustomSegmentedLEDDigit = class(TCollectionItem)
|
|
private
|
|
FLeft: Integer;
|
|
FRecalcNeeded: Boolean;
|
|
FVertAdjust: Integer;
|
|
FSegmentStates: Int64;
|
|
FSegmentRenderInfo: TSegmentRenderInfoArray;
|
|
FText: string;
|
|
protected
|
|
// Quick access to Display specified values (slant angle, digit spacing, etc)
|
|
DotSize: Integer;
|
|
SegmentWidth: Integer;
|
|
SlantAngle: Integer;
|
|
Spacing: Integer;
|
|
MaxSlantDif: Integer;
|
|
function GetBaseTop: Integer; virtual;
|
|
procedure SetBaseTop(Value: Integer); virtual;
|
|
function GetHeight: Integer; virtual;
|
|
function GetVertAdjust: Integer;
|
|
procedure SetVertAdjust(Value: Integer);
|
|
procedure SetIndex(Value: Integer); override;
|
|
function GetLeft: Integer;
|
|
procedure SetLeft(Value: Integer);
|
|
function GetWidth: Integer; virtual;
|
|
procedure SetText(Value: string); virtual;
|
|
|
|
procedure EnableAllSegs; dynamic;
|
|
function GetSegmentRenderInfo(Index: Integer; out RenderType: TSegmentRenderType;
|
|
out Points: TPointArray): Boolean;
|
|
procedure SetSegmentRenderInfo(Index: Integer; RenderType: TSegmentRenderType;
|
|
Points: array of TPoint);
|
|
function GetSegmentState(Index: Integer): Boolean;
|
|
procedure SetSegmentState(Index: Integer; Value: Boolean);
|
|
procedure SetSegmentStates(Value: Int64);
|
|
procedure UpdateText(Value: string);
|
|
procedure RecalcRefPoints; virtual; abstract;
|
|
procedure RecalcSegments; virtual; abstract;
|
|
function GetLitSegColor(Index: Integer): TColor; virtual;
|
|
function GetUnlitSegColor(Index: Integer): TColor; virtual;
|
|
function GetSegmentColor(Index: Integer): TColor;
|
|
function Display: TJvCustomSegmentedLEDDisplay;
|
|
procedure Invalidate;
|
|
procedure InvalidateStates;
|
|
procedure InvalidateRefPoints; virtual;
|
|
function NeedsPainting: Boolean;
|
|
procedure Paint;
|
|
procedure PaintSegment(Index: Integer);
|
|
|
|
class function MapperFileID: AnsiString; virtual;
|
|
|
|
property BaseTop: Integer read GetBaseTop;
|
|
property Height: Integer read GetHeight;
|
|
property Left: Integer read GetLeft;
|
|
property VertAdjust: Integer read GetVertAdjust;
|
|
property Width: Integer read GetWidth;
|
|
property Text: string read FText write SetText stored False;
|
|
|
|
property RecalcNeeded: Boolean read FRecalcNeeded;
|
|
public
|
|
constructor Create(Collection: TCollection); override;
|
|
function GetHitInfo(X, Y: Integer): TSLDHitInfo; overload;
|
|
function GetHitInfo(X, Y: Integer; out SegmentIndex: Integer): TSLDHitInfo; overload;
|
|
function PtInSegment(SegmentIndex: Integer; Pt: TPoint): Boolean; virtual;
|
|
class function SegmentCount: Integer; virtual;
|
|
class function GetSegmentName(Index: Integer): string; virtual;
|
|
class function GetSegmentIndex(Name: string): Integer; virtual;
|
|
function GetSegmentStates: Int64;
|
|
function GetSegmentString: string; virtual; abstract;
|
|
end;
|
|
|
|
TJvBaseSegmentedLEDDigit = class(TJvCustomSegmentedLEDDigit)
|
|
private
|
|
FDPWidth: Integer;
|
|
FUseDP: Boolean;
|
|
protected
|
|
// Reference points coordinates. Protected fields allows easier read/write access in descendants.
|
|
FRefLeft: Integer;
|
|
FRefCenterX: Integer;
|
|
FRefRight: Integer;
|
|
FRefTop: Integer;
|
|
FRefCenterY: Integer;
|
|
FRefBottom: Integer;
|
|
procedure EnableAllSegs; override;
|
|
procedure SetUseDP(Value: Boolean); virtual;
|
|
function GetDPWidth: Integer;
|
|
procedure SetDPWidth(Value: Integer);
|
|
procedure UpdateDPWidth; virtual;
|
|
procedure CalcASeg(Index: Integer); virtual;
|
|
procedure CalcBSeg(Index: Integer); virtual;
|
|
procedure CalcCSeg(Index: Integer); virtual;
|
|
procedure CalcDSeg(Index: Integer); virtual;
|
|
procedure CalcESeg(Index: Integer); virtual;
|
|
procedure CalcFSeg(Index: Integer); virtual;
|
|
procedure CalcGSeg(Index: Integer); virtual;
|
|
procedure CalcDPSeg(Index: Integer); virtual;
|
|
function GetWidth: Integer; override;
|
|
procedure InvalidateRefPoints; override;
|
|
procedure RecalcRefPoints; override;
|
|
procedure RecalcSegments; override;
|
|
|
|
property DPWidth: Integer read GetDPWidth write SetDPWidth;
|
|
property UseDP: Boolean read FUseDP write SetUseDP;
|
|
public
|
|
class function SegmentCount: Integer; override;
|
|
class function GetSegmentName(Index: Integer): string; override;
|
|
class function GetSegmentIndex(Name: string): Integer; override;
|
|
function GetSegmentString: string; override;
|
|
end;
|
|
|
|
TJvSegmentedLEDCharacterMapper = class(TPersistent)
|
|
private
|
|
FCurDigit: TJvCustomSegmentedLEDDigit;
|
|
FTextForDigit: string;
|
|
FSegMapRemoves: Boolean;
|
|
FActiveMapping: array[Char] of Int64;
|
|
FMappingChanged: Boolean;
|
|
FDisplay: TJvCustomSegmentedLEDDisplay;
|
|
protected
|
|
function GetCharMapping(Chr: Char): Int64;
|
|
procedure SetCharMapping(Chr: Char; Value: Int64);
|
|
function MaxSegments: Integer; dynamic;
|
|
function MapToSeparators: Boolean; dynamic;
|
|
procedure PrimReadMapping(const HdrInfo: TSegCharMapHeader; Stream: TStream); dynamic;
|
|
function UpdateStates(var Segments: Int64; SegMask: Int64): Boolean;
|
|
procedure HandleDecimalSeparator(var Text: PChar; var Segments: Int64); virtual;
|
|
function CharToSegments(Ch: Char; var Segments: Int64): Boolean; virtual;
|
|
procedure ControlItemToSegments(var ControlItem: PChar; var Segments: Int64); virtual;
|
|
procedure MapControlItems(var Text: PChar; var Segments: Int64); virtual;
|
|
procedure MapSimpleText(var Text: PChar; var Segments: Int64); virtual;
|
|
procedure MapSegNamesToSegments(var Text: PChar; var Segments: Int64); virtual;
|
|
procedure PrimMapText(var Text: PChar; var Segments: Int64); virtual;
|
|
procedure Modified;
|
|
|
|
property CurDigit: TJvCustomSegmentedLEDDigit read FCurDigit;
|
|
property Display: TJvCustomSegmentedLEDDisplay read FDisplay;
|
|
property SegMapRemoves: Boolean read FSegMapRemoves write FSegMapRemoves;
|
|
property TextForDigit: string read FTextForDigit write FTextForDigit;
|
|
property MappingChanged: Boolean read FMappingChanged;
|
|
public
|
|
constructor Create(ADisplay: TJvCustomSegmentedLEDDisplay);
|
|
procedure MapText(var Text: PChar; ADigit: TJvCustomSegmentedLEDDigit);
|
|
procedure Clear;
|
|
procedure LoadDefaultMapping; dynamic;
|
|
procedure LoadFromFile(const FileName: string);
|
|
procedure LoadFromStream(Stream: TStream);
|
|
procedure SaveToFile(const FileName: string);
|
|
procedure SaveToStream(Stream: TStream); dynamic;
|
|
|
|
property CharMapping[Chr: Char]: Int64 read GetCharMapping write SetCharMapping;
|
|
end;
|
|
|
|
// 7-segmented digit
|
|
T7SegColonUsage = (scuNone, scuLowOnly, scuFull, scuColonOnly);
|
|
TJv7SegmentedLEDDigit = class(TJvBaseSegmentedLEDDigit)
|
|
private
|
|
FUseColon: T7SegColonUsage;
|
|
protected
|
|
procedure EnableAllSegs; override;
|
|
function GetUseColon: T7SegColonUsage;
|
|
procedure SetUseColon(Value: T7SegColonUsage);
|
|
procedure RecalcSegments; override;
|
|
class function MapperFileID: AnsiString; override;
|
|
procedure CalcCHSeg(Index: Integer); virtual;
|
|
procedure CalcCLSeg(Index: Integer); virtual;
|
|
public
|
|
class function SegmentCount: Integer; override;
|
|
class function GetSegmentName(Index: Integer): string; override;
|
|
class function GetSegmentIndex(Name: string): Integer; override;
|
|
published
|
|
property UseDP;
|
|
property UseColon: T7SegColonUsage read GetUseColon write SetUseColon;
|
|
property Text;
|
|
end;
|
|
|
|
// 14-segmented digit
|
|
TJv14SegmentedLEDDigit = class(TJvBaseSegmentedLEDDigit)
|
|
protected
|
|
procedure RecalcSegments; override;
|
|
class function MapperFileID: AnsiString; override;
|
|
procedure CalcG1Seg(Index: Integer); virtual;
|
|
procedure CalcG2Seg(Index: Integer); virtual;
|
|
procedure CalcHSeg(Index: Integer); virtual;
|
|
procedure CalcISeg(Index: Integer); virtual;
|
|
procedure CalcJSeg(Index: Integer); virtual;
|
|
procedure CalcKSeg(Index: Integer); virtual;
|
|
procedure CalcLSeg(Index: Integer); virtual;
|
|
procedure CalcMSeg(Index: Integer); virtual;
|
|
public
|
|
class function SegmentCount: Integer; override;
|
|
class function GetSegmentName(Index: Integer): string; override;
|
|
class function GetSegmentIndex(Name: string): Integer; override;
|
|
published
|
|
property UseDP;
|
|
property Text;
|
|
end;
|
|
|
|
// 16-segmented digit
|
|
TJv16SegmentedLEDDigit = class(TJv14SegmentedLEDDigit)
|
|
protected
|
|
procedure RecalcSegments; override;
|
|
class function MapperFileID: AnsiString; override;
|
|
procedure CalcA1Seg(Index: Integer); virtual;
|
|
procedure CalcA2Seg(Index: Integer); virtual;
|
|
procedure CalcD1Seg(Index: Integer); virtual;
|
|
procedure CalcD2Seg(Index: Integer); virtual;
|
|
procedure CalcISeg(Index: Integer); override;
|
|
procedure CalcLSeg(Index: Integer); override;
|
|
public
|
|
class function SegmentCount: Integer; override;
|
|
class function GetSegmentName(Index: Integer): string; override;
|
|
class function GetSegmentIndex(Name: string): Integer; override;
|
|
published
|
|
property UseDP;
|
|
property Text;
|
|
end;
|
|
|
|
// TUnlitColor support routines
|
|
function IdentToUnlitColor(const Ident: string; var Int: Longint): Boolean;
|
|
function UnlitColorToIdent(Int: Longint; var Ident: string): Boolean;
|
|
function StringToUnlitColor(const S: string): TUnlitColor;
|
|
function UnlitColorToString(const Color: TUnlitColor): string;
|
|
// DigitClass registration routines
|
|
function DigitClassList: TThreadList;
|
|
procedure RegisterSegmentedLEDDigitClass(DigitClass: TJvSegmentedLEDDigitClass);
|
|
procedure RegisterSegmentedLEDDigitClasses(DigitClasses: array of TJvSegmentedLEDDigitClass);
|
|
procedure UnregisterSegmentedLEDDigitClass(DigitClass: TJvSegmentedLEDDigitClass);
|
|
procedure UnregisterSegmentedLEDDigitClasses(DigitClasses: array of TJvSegmentedLEDDigitClass);
|
|
procedure UnregisterModuleSegmentedLEDDigitClasses(Module: HMODULE);
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_39/run/JvSegmentedLEDDisplay.pas $';
|
|
Revision: '$Revision: 12461 $';
|
|
Date: '$Date: 2009-08-14 19:21:33 +0200 (ven., 14 août 2009) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
Controls, SysUtils,
|
|
JclGraphUtils,
|
|
{$IFNDEF COMPILER12_UP}
|
|
JvJCLUtils,
|
|
{$ENDIF ~COMPILER12_UP}
|
|
JvThemes, JvConsts, JvResources;
|
|
|
|
{$R JvSegmentedLEDDisplay.res}
|
|
|
|
var
|
|
GDigitClassList: TThreadList = nil;
|
|
|
|
//=== DigitClass registration routines =======================================
|
|
|
|
function DigitClassList: TThreadList;
|
|
begin
|
|
if GDigitClassList = nil then
|
|
GDigitClassList := TThreadList.Create;
|
|
Result := GDigitClassList;
|
|
end;
|
|
|
|
procedure RegisterSegmentedLEDDigitClass(DigitClass: TJvSegmentedLEDDigitClass);
|
|
begin
|
|
with DigitClassList.LockList do
|
|
try
|
|
if IndexOf(DigitClass) > -1 then
|
|
raise EJVCLSegmentedLEDException.CreateRes(@RsEDuplicateDigitClass);
|
|
Add(DigitClass);
|
|
Classes.RegisterClass(DigitClass);
|
|
finally
|
|
DigitClassList.UnlockList;
|
|
end;
|
|
end;
|
|
|
|
procedure RegisterSegmentedLEDDigitClasses(DigitClasses: array of TJvSegmentedLEDDigitClass);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(DigitClasses) to High(DigitClasses) do
|
|
RegisterSegmentedLEDDigitClass(DigitClasses[I]);
|
|
end;
|
|
|
|
procedure UnregisterSegmentedLEDDigitClass(DigitClass: TJvSegmentedLEDDigitClass);
|
|
begin
|
|
DigitClassList.Remove(DigitClass);
|
|
end;
|
|
|
|
procedure UnregisterSegmentedLEDDigitClasses(DigitClasses: array of TJvSegmentedLEDDigitClass);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(DigitClasses) to High(DigitClasses) do
|
|
UnregisterSegmentedLEDDigitClass(DigitClasses[I]);
|
|
end;
|
|
|
|
procedure UnregisterModuleSegmentedLEDDigitClasses(Module: HMODULE);
|
|
{$IFDEF UNIX}
|
|
begin
|
|
// ?
|
|
end;
|
|
{$ENDIF UNIX}
|
|
{$IFDEF MSWINDOWS}
|
|
var
|
|
I: Integer;
|
|
M: TMemoryBasicInformation;
|
|
begin
|
|
with DigitClassList.LockList do
|
|
try
|
|
for I := Count - 1 downto 0 do
|
|
begin
|
|
VirtualQuery(Items[I], M, SizeOf(M));
|
|
if (Module = 0) or (HMODULE(M.AllocationBase) = Module) then
|
|
Delete(I);
|
|
end;
|
|
finally
|
|
DigitClassList.UnlockList;
|
|
end;
|
|
end;
|
|
{$ENDIF MSWINDOWS}
|
|
|
|
|
|
//=== Helper routine: AngleAdjustPoint =======================================
|
|
|
|
function AngleAdjustPoint(X, Y, Angle: Integer): TPoint;
|
|
begin
|
|
Result.X := X - Trunc(ArcTan(Angle * Pi / 180.0) * Y);
|
|
Result.Y := Y;
|
|
end;
|
|
|
|
//=== Helper routine: TextIndex ==============================================
|
|
|
|
function TextIndex(S: string; const Strings: array of string): Integer;
|
|
begin
|
|
Result := High(Strings);
|
|
while (Result > -1) and not AnsiSameText(S, Strings[Result]) do
|
|
Dec(Result);
|
|
end;
|
|
|
|
//=== { TJvCustomSegmentedLEDDisplay } =======================================
|
|
|
|
constructor TJvCustomSegmentedLEDDisplay.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
IncludeThemeStyle(Self, [csParentBackground]);
|
|
AutoSize := True;
|
|
FDigitClass := TJv7SegmentedLEDDigit;
|
|
FCharacterMapper := TJvSegmentedLEDCharacterMapper.Create(Self);
|
|
FDigits := TJvSegmentedLEDDigits.Create(Self);
|
|
FDigitHeight := 30;
|
|
FDigitSpacing := 2;
|
|
FDigitWidth := 20;
|
|
FDotSize := 4;
|
|
FSegmentLitColor := clWindowText;
|
|
FSegmentSpacing := 2;
|
|
FSegmentThickness := 2;
|
|
FSegmentUnlitColor := clDefaultLitColor;
|
|
ClientWidth := 20;
|
|
ClientHeight := 30;
|
|
end;
|
|
|
|
destructor TJvCustomSegmentedLEDDisplay.Destroy;
|
|
begin
|
|
FreeAndNil(FDigits);
|
|
FreeAndNil(FCharacterMapper);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.DefineProperties(Filer: TFiler);
|
|
begin
|
|
inherited DefineProperties(Filer);
|
|
Filer.DefineBinaryProperty('MapperData', CharacterMapper.LoadFromStream,
|
|
CharacterMapper.SaveToStream, CharacterMapper.MappingChanged);
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
RemapText;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.Paint;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Canvas.Brush.Color := Color;
|
|
Canvas.Brush.Style := bsSolid;
|
|
Canvas.Pen.Style := psSolid;
|
|
DrawThemedBackground(Self, Canvas, ClientRect);
|
|
for I := 0 to FDigits.Count - 1 do
|
|
Digits[I].Paint;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDisplay.GetText: string;
|
|
begin
|
|
Result := FText;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetText(Value: string);
|
|
begin
|
|
if Value <> Text then
|
|
PrimSetText(Value);
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDigitHeight(Value: Integer);
|
|
var
|
|
MaxHeight: Integer;
|
|
I: Integer;
|
|
begin
|
|
if Value <> DigitHeight then
|
|
begin
|
|
FDigitHeight := Value;
|
|
MaxHeight := 0;
|
|
for I := 0 to Digits.Count -1 do
|
|
begin
|
|
Digits[I].InvalidateRefPoints;
|
|
if Digits[I].Height + Digits[I].GetVertAdjust > MaxHeight then
|
|
MaxHeight := Digits[I].Height + Digits[I].GetVertAdjust;
|
|
end;
|
|
if MaxHeight = 0 then
|
|
MaxHeight := 13;
|
|
// Adjust control height
|
|
if AutoSize and not (Align in [alLeft, alRight, alClient]) and
|
|
(Anchors * [akTop, akBottom] <> [akTop, akBottom]) and (ClientHeight <> MaxHeight) then
|
|
ClientHeight := MaxHeight;
|
|
InvalidateView;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDigits(Value: TJvSegmentedLEDDigits);
|
|
begin
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDigitSpacing(Value: Integer);
|
|
begin
|
|
if Value <> DigitSpacing then
|
|
begin
|
|
FDigitSpacing := Value;
|
|
UpdateDigitsPositions;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDigitWidth(Value: Integer);
|
|
begin
|
|
if Value <> DigitWidth then
|
|
begin
|
|
FDigitWidth := Value;
|
|
if Digits.Count > 0 then
|
|
begin
|
|
UpdateDigitsPositions;
|
|
Digits[0].InvalidateRefPoints;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDigitClass(Value: TJvSegmentedLEDDigitClass);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (DigitClass <> Value) and (Value <> nil) then
|
|
begin
|
|
FDigitClass := Value;
|
|
I := Digits.Count;
|
|
FreeAndNil(FDigits);
|
|
FDigits := TJvSegmentedLEDDigits.Create(Self);
|
|
while (I > 0) do
|
|
begin
|
|
Digits.Add;
|
|
Dec(I);
|
|
end;
|
|
if CharacterMapper <> nil then
|
|
CharacterMapper.LoadDefaultMapping;
|
|
if not (csLoading in ComponentState) then
|
|
RemapText;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDotSize(Value: Integer);
|
|
begin
|
|
Value := Value and not 1;
|
|
if Value <> DotSize then
|
|
begin
|
|
FDotSize := Value;
|
|
InvalidateDigits;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetSegmentLitColor(Value: TColor);
|
|
begin
|
|
if Value <> SegmentLitColor then
|
|
begin
|
|
FSegmentLitColor := Value;
|
|
InvalidateView;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetSegmentSpacing(Value: Integer);
|
|
begin
|
|
Value := Value and not 1;
|
|
if Value <> SegmentSpacing then
|
|
begin
|
|
FSegmentSpacing := Value;
|
|
InvalidateDigits;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetSegmentThickness(Value: Integer);
|
|
begin
|
|
Value := Value and not 1;
|
|
if Value <> SegmentThickness then
|
|
begin
|
|
FSegmentThickness := Value;
|
|
InvalidateDigits;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetSegmentUnlitColor(Value: TUnlitColor);
|
|
begin
|
|
if Value <> SegmentUnlitColor then
|
|
begin
|
|
FSegmentUnlitColor := Value;
|
|
InvalidateView;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetSlant(Value: TSlantAngle);
|
|
begin
|
|
if Value <> Slant then
|
|
begin
|
|
FSlant := Value;
|
|
InvalidateDigits;
|
|
UpdateDigitsPositions;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
function TJvCustomSegmentedLEDDisplay.GetDigitClassName: TJvSegmentedLEDDigitClassName;
|
|
begin
|
|
if DigitClass <> nil then
|
|
Result := DigitClass.ClassName
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.SetDigitClassName(Value: TJvSegmentedLEDDigitClassName);
|
|
var
|
|
AClass: TClass;
|
|
begin
|
|
if not AnsiSameStr(Value, DigitClassName) then
|
|
begin
|
|
if Value <> '' then
|
|
begin
|
|
AClass := FindClass(Value);
|
|
if AClass.InheritsFrom(TJvCustomSegmentedLEDDigit) then
|
|
DigitClass := TJvSegmentedLEDDigitClass(FindClass(Value))
|
|
else
|
|
raise EJVCLSegmentedLEDException.CreateRes(@RsEInvalidClass);
|
|
end
|
|
else
|
|
DigitClass := nil;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDisplay.GetRealUnlitColor: TColor;
|
|
begin
|
|
if SegmentUnlitColor = clNone then
|
|
Result := Color
|
|
else
|
|
if SegmentUnlitColor = clDefaultBackground then
|
|
Result := CalcRealUnlitColorBackground
|
|
else
|
|
if SegmentUnlitColor = clDefaultLitColor then
|
|
Result := CalcRealUnlitColorLitColor
|
|
else
|
|
Result := SegmentUnlitColor;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDisplay.CalcRealUnlitColorBackground: TColor;
|
|
var
|
|
Int: Integer;
|
|
begin
|
|
Int := Intensity(Color32(Color));
|
|
if Int > 127 then
|
|
{ Light color; darken a little }
|
|
Result := DarkColor(Color, 30)
|
|
else
|
|
{ Dark color; lighten a little }
|
|
Result := BrightColor(Color, 30);
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDisplay.CalcRealUnlitColorLitColor: TColor;
|
|
begin
|
|
if Intensity(Color32(SegmentLitColor)) > Intensity(Color32(Color)) then
|
|
Result := DarkColor(SegmentLitColor, 70)
|
|
else
|
|
Result := BrightColor(SegmentLitColor, 70);
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.PrimSetText(Value: string);
|
|
var
|
|
P: PChar;
|
|
I: Integer;
|
|
begin
|
|
{ Apply mapping of text. If any digit is changed Invalidate will be called. The stored value for
|
|
FText will be the concatenation of each Digit's Text value. }
|
|
if CharacterMapper <> nil then
|
|
begin
|
|
P := PChar(Value);
|
|
for I := 0 to Digits.Count -1 do
|
|
CharacterMapper.MapText(P, Digits[I]);
|
|
UpdateText;
|
|
end
|
|
else
|
|
FText := Value;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.BaseTopChanged;
|
|
var
|
|
I: Integer;
|
|
MaxHeight: Integer;
|
|
begin
|
|
// Determine MaxBaseTop
|
|
FMaxBaseTop := 0;
|
|
for I := 0 to Digits.Count - 1 do
|
|
if Digits[I].GetBaseTop > FMaxBaseTop then
|
|
FMaxBaseTop := Digits[I].GetBaseTop;
|
|
// Vertically adjust digits and determine maximum height
|
|
MaxHeight := 0;
|
|
for I := 0 to Digits.Count - 1 do
|
|
begin
|
|
Digits[I].SetVertAdjust(FMaxBaseTop - Digits[I].GetBaseTop);
|
|
if Digits[I].Height + Digits[I].GetVertAdjust > MaxHeight then
|
|
MaxHeight := Digits[I].Height + Digits[I].GetVertAdjust;
|
|
end;
|
|
if MaxHeight = 0 then
|
|
MaxHeight := 13;
|
|
// Adjust control height
|
|
if AutoSize and not (Align in [alLeft, alRight, alClient]) and
|
|
(Anchors * [akTop, akBottom] <> [akTop, akBottom]) and (ClientHeight <> MaxHeight) then
|
|
begin
|
|
InvalidateView;
|
|
ClientHeight := MaxHeight;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.HeightChanged;
|
|
var
|
|
MaxHeight: Integer;
|
|
I: Integer;
|
|
begin
|
|
MaxHeight := 0;
|
|
for I := 0 to Digits.Count - 1 do
|
|
if Digits[I].Height + Digits[I].GetVertAdjust > MaxHeight then
|
|
MaxHeight := Digits[I].Height + Digits[I].GetVertAdjust;
|
|
if MaxHeight = 0 then
|
|
MaxHeight := 13;
|
|
// Adjust control height
|
|
if AutoSize and not (Align in [alLeft, alRight, alClient]) and
|
|
(Anchors * [akTop, akBottom] <> [akTop, akBottom]) and (ClientHeight <> MaxHeight) then
|
|
begin
|
|
InvalidateView;
|
|
ClientHeight := MaxHeight;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.UpdateDigitsPositions;
|
|
var
|
|
I: Integer;
|
|
X: Integer;
|
|
begin
|
|
if Digits.Count > 0 then
|
|
begin
|
|
Digits[0].SetLeft(0);
|
|
X := Digits[0].Width + DigitSpacing;
|
|
for I := 1 to Digits.Count - 1 do
|
|
begin
|
|
Digits[I].SetLeft(X);
|
|
Inc(X, Digits[I].Width + DigitSpacing);
|
|
end;
|
|
Dec(X, DigitSpacing);
|
|
if AutoSize and not (Align in [alTop, alBottom, alClient]) and
|
|
(Anchors * [akLeft, akRight] <> [akLeft, akRight]) and (ClientWidth <> X) then
|
|
ClientWidth := X;
|
|
InvalidateView;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.InvalidateDigits;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Digits.Count - 1 do
|
|
Digits[I].InvalidateRefPoints;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.InvalidateView;
|
|
begin
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.UpdateText;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FText := '';
|
|
for I := 0 to Digits.Count - 1 do
|
|
FText := FText + Digits[I].Text;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.UpdateBounds;
|
|
begin
|
|
HeightChanged;
|
|
UpdateDigitsPositions;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDisplay.RemapText;
|
|
begin
|
|
PrimSetText(Text);
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDisplay.GetHitInfo(X, Y: Integer): TSLDHitInfo;
|
|
var
|
|
DummyDigit: TJvCustomSegmentedLEDDigit;
|
|
DummyIndex: Integer;
|
|
begin
|
|
Result := GetHitInfo(X, Y, DummyDigit, DummyIndex);
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDisplay.GetHitInfo(X, Y: Integer;
|
|
out Digit: TJvCustomSegmentedLEDDigit; out SegmentIndex: Integer): TSLDHitInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := shiNowhere;
|
|
if PtInRect(ClientRect, Point(X, Y)) then
|
|
begin
|
|
// Iterate over each digit and get the hit info from them
|
|
I := Digits.Count;
|
|
while (I > 0) and (Result = shiNowhere) do
|
|
begin
|
|
Dec(I);
|
|
Result := Digits[I].GetHitInfo(X, Y, SegmentIndex);
|
|
end;
|
|
if Result <> shiNowhere then
|
|
Digit := Digits[I]
|
|
else // Result = shiNowhere, but we are in fact in the client area of the control (see outer if)
|
|
Result := shiClientArea;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvSegmentedLEDDigits } ==============================================
|
|
|
|
constructor TJvSegmentedLEDDigits.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner, TJvCustomSegmentedLEDDisplay(AOwner).DigitClass);
|
|
end;
|
|
|
|
function TJvSegmentedLEDDigits.GetItem(Index: Integer): TJvCustomSegmentedLEDDigit;
|
|
begin
|
|
Result := TJvCustomSegmentedLEDDigit(inherited Items[Index]);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDDigits.SetItem(Index: Integer; Value: TJvCustomSegmentedLEDDigit);
|
|
begin
|
|
inherited Items[Index] := Value;
|
|
end;
|
|
|
|
function TJvSegmentedLEDDigits.Display: TJvCustomSegmentedLEDDisplay;
|
|
begin
|
|
Result := TJvCustomSegmentedLEDDisplay(GetOwner);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDDigits.Update(Item: TCollectionItem);
|
|
begin
|
|
Assert(Display <> nil);
|
|
Display.UpdateBounds;
|
|
end;
|
|
|
|
//=== { TJvCustomSegmentedLEDDigit } =========================================
|
|
|
|
constructor TJvCustomSegmentedLEDDigit.Create(Collection: TCollection);
|
|
begin
|
|
inherited Create(Collection);
|
|
InvalidateRefPoints;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetBaseTop: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetBaseTop(Value: Integer);
|
|
begin
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetHeight: Integer;
|
|
begin
|
|
Result := Display.DigitHeight;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetVertAdjust: Integer;
|
|
begin
|
|
Result := FVertAdjust;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetVertAdjust(Value: Integer);
|
|
begin
|
|
if Value <> GetVertAdjust then
|
|
begin
|
|
FVertAdjust := Value;
|
|
InvalidateRefPoints;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetIndex(Value: Integer);
|
|
begin
|
|
inherited SetIndex(Value);
|
|
Display.UpdateDigitsPositions;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetLeft: Integer;
|
|
begin
|
|
Result := FLeft;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetLeft(Value: Integer);
|
|
begin
|
|
if Value <> Left then
|
|
begin
|
|
FLeft := Value;
|
|
InvalidateRefPoints;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetWidth: Integer;
|
|
begin
|
|
Result := Display.DigitWidth + MaxSlantDif;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetText(Value: string);
|
|
var
|
|
P: PChar;
|
|
begin
|
|
if Value <> Text then
|
|
begin
|
|
if Display.CharacterMapper <> nil then
|
|
begin
|
|
P := PChar(Value);
|
|
Display.CharacterMapper.MapText(P, Self);
|
|
end
|
|
else
|
|
UpdateText(Value);
|
|
Display.UpdateText;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.EnableAllSegs;
|
|
begin
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetSegmentRenderInfo(Index: Integer;
|
|
out RenderType: TSegmentRenderType; out Points: TPointArray): Boolean;
|
|
begin
|
|
Result := (Index >= 0) and (Index < SegmentCount);
|
|
if Result then
|
|
begin
|
|
RenderType := FSegmentRenderInfo[Index].RenderType;
|
|
Points := FSegmentRenderInfo[Index].Points;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetSegmentRenderInfo(Index: Integer;
|
|
RenderType: TSegmentRenderType; Points: array of TPoint);
|
|
begin
|
|
FSegmentRenderInfo[Index].RenderType := RenderType;
|
|
SetLength(FSegmentRenderInfo[Index].Points, Length(Points));
|
|
if Length(Points) > 0 then
|
|
Move(Points[0], FSegmentRenderInfo[Index].Points[0], Length(Points) * SizeOf(Points[0]));
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetSegmentState(Index: Integer): Boolean;
|
|
begin
|
|
Result := (FSegmentStates and (1 shl Index)) <> 0;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetSegmentState(Index: Integer; Value: Boolean);
|
|
begin
|
|
if Value <> GetSegmentState(Index) then
|
|
begin
|
|
FSegmentStates := FSegmentStates xor (1 shl Index);
|
|
InvalidateStates;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.SetSegmentStates(Value: Int64);
|
|
begin
|
|
if Value <> FSegmentStates then
|
|
begin
|
|
FSegmentStates := Value;
|
|
InvalidateStates;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.UpdateText(Value: string);
|
|
begin
|
|
if Value <> Text then
|
|
begin
|
|
FText := Value;
|
|
Display.UpdateText;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetLitSegColor(Index: Integer): TColor;
|
|
begin
|
|
Result := Display.SegmentLitColor;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetUnlitSegColor(Index: Integer): TColor;
|
|
begin
|
|
Result := Display.GetRealUnlitColor;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetSegmentColor(Index: Integer): TColor;
|
|
begin
|
|
if GetSegmentState(Index) then
|
|
Result := GetLitSegColor(Index)
|
|
else
|
|
Result := GetUnlitSegColor(Index);
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.Display: TJvCustomSegmentedLEDDisplay;
|
|
begin
|
|
Assert(Collection <> nil);
|
|
Result := TJvSegmentedLEDDigits(Collection).Display;
|
|
Assert(Result <> nil);
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.Invalidate;
|
|
begin
|
|
Display.Invalidate;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.InvalidateStates;
|
|
begin
|
|
Display.Invalidate;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.InvalidateRefPoints;
|
|
begin
|
|
SlantAngle := Display.Slant;
|
|
Spacing := Display.SegmentSpacing;
|
|
SegmentWidth := Display.SegmentThickness;
|
|
DotSize := Display.DotSize;
|
|
|
|
MaxSlantDif := Trunc(Abs(ArcTan(SlantAngle * Pi / 180.0) * Display.DigitHeight));
|
|
FRecalcNeeded := True;
|
|
|
|
SetLength(FSegmentRenderInfo, 0);
|
|
SetLength(FSegmentRenderInfo, SegmentCount);
|
|
FillChar(FSegmentRenderInfo[0], SegmentCount * SizeOf(FSegmentRenderInfo[0]), 0);
|
|
Display.InvalidateView;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.NeedsPainting: Boolean;
|
|
begin
|
|
Result := FRecalcNeeded;
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.Paint;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if RecalcNeeded then
|
|
begin
|
|
RecalcRefPoints;
|
|
RecalcSegments;
|
|
FRecalcNeeded := False;
|
|
end;
|
|
for I := 0 to SegmentCount - 1 do
|
|
PaintSegment(I);
|
|
end;
|
|
|
|
procedure TJvCustomSegmentedLEDDigit.PaintSegment(Index: Integer);
|
|
var
|
|
SegColor: TColor;
|
|
begin
|
|
SegColor := GetSegmentColor(Index);
|
|
Display.Canvas.Brush.Color := SegColor;
|
|
Display.Canvas.Pen.Color := SegColor;
|
|
case FSegmentRenderInfo[Index].RenderType of
|
|
srtPolygon:
|
|
Display.Canvas.Polygon(FSegmentRenderInfo[Index].Points);
|
|
srtCircle:
|
|
Display.Canvas.Ellipse(
|
|
FSegmentRenderInfo[Index].Points[0].X, FSegmentRenderInfo[Index].Points[0].Y,
|
|
FSegmentRenderInfo[Index].Points[1].X, FSegmentRenderInfo[Index].Points[1].Y);
|
|
srtRect:
|
|
Display.Canvas.Rectangle(
|
|
FSegmentRenderInfo[Index].Points[0].X, FSegmentRenderInfo[Index].Points[0].Y,
|
|
FSegmentRenderInfo[Index].Points[1].X, FSegmentRenderInfo[Index].Points[1].Y);
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetHitInfo(X, Y: Integer): TSLDHitInfo;
|
|
var
|
|
DummyIndex: Integer;
|
|
begin
|
|
Result := GetHitInfo(X, Y, DummyIndex);
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetHitInfo(X, Y: Integer;
|
|
out SegmentIndex: Integer): TSLDHitInfo;
|
|
begin
|
|
Result := shiNowhere;
|
|
if PtInRect(Rect(Left, 0, Width, Height + BaseTop), Point(X, Y)) then
|
|
begin
|
|
SegmentIndex := SegmentCount - 1;
|
|
while (SegmentIndex >= 0) and not PtInSegment(SegmentIndex, Point(X, Y)) do
|
|
Dec(SegmentIndex);
|
|
if SegmentIndex > -1 then
|
|
Result := shiDigitSegment
|
|
else
|
|
Result := shiDigit;
|
|
end;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.PtInSegment(SegmentIndex: Integer; Pt: TPoint): Boolean;
|
|
var
|
|
SegType: TSegmentRenderType;
|
|
SegPts: TPointArray;
|
|
Rgn: HRGN;
|
|
begin
|
|
if GetSegmentRenderInfo(SegmentIndex, SegType, SegPts) then
|
|
begin
|
|
case SegType of
|
|
srtNone:
|
|
Result := False;
|
|
srtPolygon:
|
|
begin
|
|
Rgn := CreatePolygonRgn(SegPts[0], Length(SegPts), WINDING);
|
|
try
|
|
if Rgn <> NullHandle then
|
|
Result := PtInRegion(Rgn, Pt.X, Pt.Y)
|
|
else
|
|
Result := False;
|
|
finally
|
|
DeleteObject(Rgn);
|
|
end;
|
|
end;
|
|
srtRect:
|
|
Result := PtInRect(Rect(SegPts[0].X, SegPts[0].Y, SegPts[1].X, SegPts[1].Y), Pt);
|
|
srtCircle:
|
|
begin
|
|
Rgn := CreateEllipticRgn(SegPts[0].X, SegPts[0].Y, SegPts[1].X, SegPts[1].Y);
|
|
try
|
|
if Rgn <> NullHandle then
|
|
Result := PtInRegion(Rgn, Pt.X, Pt.Y)
|
|
else
|
|
Result := False;
|
|
finally
|
|
DeleteObject(Rgn);
|
|
end;
|
|
end;
|
|
else
|
|
Result := False; // Call method to check additional render types?
|
|
end;
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvCustomSegmentedLEDDigit.GetSegmentStates: Int64;
|
|
begin
|
|
Result := FSegmentStates;
|
|
end;
|
|
|
|
class function TJvCustomSegmentedLEDDigit.MapperFileID: AnsiString;
|
|
begin
|
|
// DO NOTHING.
|
|
// THIS CAN'T BE AN ABSTRACT CLASS METHOD AS THIS IS NOT
|
|
// SUPPORTED BY C++ BUILDER
|
|
end;
|
|
|
|
class function TJvCustomSegmentedLEDDigit.GetSegmentIndex(
|
|
Name: string): Integer;
|
|
begin
|
|
// DO NOTHING.
|
|
// THIS CAN'T BE AN ABSTRACT CLASS METHOD AS THIS IS NOT
|
|
// SUPPORTED BY C++ BUILDER
|
|
Result := 0;
|
|
end;
|
|
|
|
class function TJvCustomSegmentedLEDDigit.GetSegmentName(
|
|
Index: Integer): string;
|
|
begin
|
|
// DO NOTHING.
|
|
// THIS CAN'T BE AN ABSTRACT CLASS METHOD AS THIS IS NOT
|
|
// SUPPORTED BY C++ BUILDER
|
|
Result := '';
|
|
end;
|
|
|
|
class function TJvCustomSegmentedLEDDigit.SegmentCount: Integer;
|
|
begin
|
|
// DO NOTHING.
|
|
// THIS CAN'T BE AN ABSTRACT CLASS METHOD AS THIS IS NOT
|
|
// SUPPORTED BY C++ BUILDER
|
|
Result := 0;
|
|
end;
|
|
|
|
//=== { TJvBaseSegmentedLEDDigit } ===========================================
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.EnableAllSegs;
|
|
begin
|
|
inherited EnableAllSegs;
|
|
UseDP := True;
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.SetUseDP(Value: Boolean);
|
|
begin
|
|
if Value <> UseDP then
|
|
begin
|
|
FUseDP := Value;
|
|
UpdateDPWidth;
|
|
InvalidateRefPoints;
|
|
end;
|
|
end;
|
|
|
|
function TJvBaseSegmentedLEDDigit.GetDPWidth: Integer;
|
|
begin
|
|
Result := FDPWidth;
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.SetDPWidth(Value: Integer);
|
|
begin
|
|
if Value <> DPWidth then
|
|
begin
|
|
FDPWidth := Value;
|
|
Display.UpdateDigitsPositions;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.UpdateDPWidth;
|
|
begin
|
|
if UseDP then
|
|
begin
|
|
// Determine if width will suffice for the DP, otherwise set FDPWidth to the required additional width
|
|
if MaxSlantDif < (Spacing + DotSize) then
|
|
DPWidth := Spacing + DotSize - MaxSlantDif
|
|
else
|
|
DPWidth := 0;
|
|
end
|
|
else
|
|
DPWidth := 0;
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcASeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2, FRefTop, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2, FRefTop, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth, FRefTop + SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth, FRefTop + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcBSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefRight, FRefTop + Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight, FRefCenterY - Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - SegmentWidth, FRefCenterY - Spacing div 2 - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - SegmentWidth, FRefTop + Spacing div 2 + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcCSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefRight, FRefCenterY + Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight, FRefBottom - Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - SegmentWidth, FRefBottom - Spacing div 2 - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - SegmentWidth, FRefCenterY + Spacing div 2 + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcDSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2, FRefBottom, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2, FRefBottom, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth, FRefBottom - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth, FRefBottom - SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcESeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft, FRefCenterY + Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft, FRefBottom - Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + SegmentWidth, FRefBottom - Spacing div 2 - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + SegmentWidth, FRefCenterY + Spacing div 2 + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcFSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft, FRefTop + Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft, FRefCenterY - Spacing div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + SegmentWidth, FRefCenterY - Spacing div 2 - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + SegmentWidth, FRefTop + Spacing div 2 + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcGSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2, FRefCenterY, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth div 2, FRefCenterY - SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth div 2, FRefCenterY - SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2, FRefCenterY, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth div 2, FRefCenterY + SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth div 2, FRefCenterY + SegmentWidth div 2, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.CalcDPSeg(Index: Integer);
|
|
var
|
|
UpperLeftPoint: TPoint;
|
|
begin
|
|
UpperLeftPoint := AngleAdjustPoint(FRefRight + Spacing, FRefBottom - DotSize, SlantAngle);
|
|
SetSegmentRenderInfo(Index, srtCircle, [
|
|
UpperLeftPoint,
|
|
Point(UpperLeftPoint.X + DotSize, UpperLeftPoint.Y + DotSize)
|
|
]);
|
|
end;
|
|
|
|
function TJvBaseSegmentedLEDDigit.GetWidth: Integer;
|
|
begin
|
|
Result := inherited GetWidth + DPWidth;
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.InvalidateRefPoints;
|
|
begin
|
|
inherited InvalidateRefPoints;
|
|
UpdateDPWidth;
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.RecalcRefPoints;
|
|
begin
|
|
FRefLeft := Left + MaxSlantDif;
|
|
FRefCenterX := FRefLeft + (Display.DigitWidth - 1) div 2;
|
|
FRefRight := FRefLeft + Display.DigitWidth - 1;
|
|
FRefTop := GetVertAdjust;
|
|
FRefCenterY := FRefTop + (Display.DigitHeight - 1) div 2;
|
|
FRefBottom := FRefTop + (Display.DigitHeight - 1);
|
|
end;
|
|
|
|
procedure TJvBaseSegmentedLEDDigit.RecalcSegments;
|
|
begin
|
|
CalcASeg(0);
|
|
CalcBSeg(1);
|
|
CalcCSeg(2);
|
|
CalcDSeg(3);
|
|
CalcESeg(4);
|
|
CalcFSeg(5);
|
|
CalcGSeg(6);
|
|
if UseDP then
|
|
CalcDPSeg(7);
|
|
end;
|
|
|
|
class function TJvBaseSegmentedLEDDigit.SegmentCount: Integer;
|
|
begin
|
|
Result := 8;
|
|
end;
|
|
|
|
class function TJvBaseSegmentedLEDDigit.GetSegmentName(Index: Integer): string;
|
|
begin
|
|
if Index < 7 then
|
|
Result := Chr(Ord('A') + Index)
|
|
else
|
|
if Index = 7 then
|
|
Result := 'DP'
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
class function TJvBaseSegmentedLEDDigit.GetSegmentIndex(Name: string): Integer;
|
|
begin
|
|
Result := -1;
|
|
Name := UpperCase(Name);
|
|
if Length(Name) = 1 then
|
|
begin
|
|
Result := Ord(Name[1]) - Ord('A');
|
|
if Result > 6 then
|
|
Result := -1;
|
|
end
|
|
else
|
|
if Name = 'DP' then
|
|
Result := 7;
|
|
end;
|
|
|
|
function TJvBaseSegmentedLEDDigit.GetSegmentString: string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := '';
|
|
for I := 0 to SegmentCount - 1 do
|
|
begin
|
|
if GetSegmentState(I) then
|
|
begin
|
|
if Length(Result) > 0 then
|
|
Result := Result + ',' + GetSegmentName(I)
|
|
else
|
|
Result := GetSegmentName(I);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvSegmentedLEDCharacterMapper } =====================================
|
|
|
|
constructor TJvSegmentedLEDCharacterMapper.Create(ADisplay: TJvCustomSegmentedLEDDisplay);
|
|
begin
|
|
inherited Create;
|
|
FDisplay := ADisplay;
|
|
LoadDefaultMapping;
|
|
end;
|
|
|
|
function TJvSegmentedLEDCharacterMapper.GetCharMapping(Chr: Char): Int64;
|
|
begin
|
|
Result := FActiveMapping[Chr];
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.SetCharMapping(Chr: Char; Value: Int64);
|
|
begin
|
|
FActiveMapping[Chr] := Value;
|
|
Modified;
|
|
end;
|
|
|
|
function TJvSegmentedLEDCharacterMapper.MaxSegments: Integer;
|
|
begin
|
|
Result := Display.DigitClass.SegmentCount;
|
|
end;
|
|
|
|
function TJvSegmentedLEDCharacterMapper.MapToSeparators: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.PrimReadMapping(const HdrInfo: TSegCharMapHeader;
|
|
Stream: TStream);
|
|
var
|
|
Chr: Char;
|
|
MapSize: Byte;
|
|
OldMapping: Int64;
|
|
begin
|
|
Clear; // clear the mapping table
|
|
MapSize := HdrInfo.Flags and 7;
|
|
for Chr := #0 to #255 do
|
|
if CharInSet(Chr, HdrInfo.MappedChars) then
|
|
Stream.ReadBuffer(FActiveMapping[Chr], MapSize);
|
|
if HdrInfo.Flags and 16 <> 0 then
|
|
begin
|
|
// Swap . for DecimalSeparator and , for ThousandSeparator
|
|
if DecimalSeparator <> '.' then
|
|
begin
|
|
OldMapping := FActiveMapping[DecimalSeparator];
|
|
FActiveMapping[DecimalSeparator] := FActiveMapping['.'];
|
|
FActiveMapping[ThousandSeparator] := OldMapping;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TJvSegmentedLEDCharacterMapper.UpdateStates(var Segments: Int64;
|
|
SegMask: Int64): Boolean;
|
|
var
|
|
OldValue: Int64;
|
|
begin
|
|
OldValue := Segments;
|
|
if FSegMapRemoves then
|
|
Segments := Segments and not SegMask
|
|
else
|
|
Segments := Segments or SegMask;
|
|
Result := Segments <> OldValue;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.HandleDecimalSeparator(var Text: PChar;
|
|
var Segments: Int64);
|
|
begin
|
|
if (CurDigit is TJvBaseSegmentedLEDDigit) and TJvBaseSegmentedLEDDigit(CurDigit).UseDP then
|
|
begin
|
|
if UpdateStates(Segments, 1 shl CurDigit.GetSegmentIndex('DP')) then
|
|
TextForDigit := TextForDigit + DecimalSeparator;
|
|
while Text[0] = DecimalSeparator do
|
|
Inc(Text);
|
|
end;
|
|
end;
|
|
|
|
function TJvSegmentedLEDCharacterMapper.CharToSegments(Ch: Char; var Segments: Int64): Boolean;
|
|
begin
|
|
Result := UpdateStates(Segments, FActiveMapping[Ch]) or (Ch = ' ');
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.ControlItemToSegments(var ControlItem: PChar;
|
|
var Segments: Int64);
|
|
var
|
|
OrdValue: Byte;
|
|
begin
|
|
case ControlItem^ of
|
|
'+':
|
|
begin
|
|
if FSegMapRemoves then
|
|
TextForDigit := TextForDigit + '+';
|
|
FSegMapRemoves := False;
|
|
Inc(ControlItem);
|
|
end;
|
|
'-':
|
|
begin
|
|
if not FSegMapRemoves then
|
|
TextForDigit := TextForDigit + '-';
|
|
FSegMapRemoves := True;
|
|
Inc(ControlItem);
|
|
end;
|
|
'&':
|
|
begin
|
|
Inc(ControlItem);
|
|
if CharToSegments(ControlItem^, Segments) then
|
|
TextForDigit := TextForDigit + '&' + ControlItem[0];
|
|
Inc(ControlItem);
|
|
end;
|
|
'#':
|
|
begin
|
|
Inc(ControlItem);
|
|
OrdValue := 0;
|
|
while CharInSet(ControlItem[0], DigitSymbols) do
|
|
begin
|
|
if OrdValue >= 100 then
|
|
OrdValue := OrdValue mod 100;
|
|
if OrdValue >= 26 then
|
|
OrdValue := OrdValue mod 10;
|
|
OrdValue := OrdValue * 10 + (Ord(ControlItem[0]) - Ord('0'));
|
|
Inc(ControlItem);
|
|
end;
|
|
if CharToSegments(Chr(OrdValue), Segments) then
|
|
begin
|
|
if OrdValue in [32 .. 127] then
|
|
TextForDigit := TextForDigit + '&' + Chr(OrdValue)
|
|
else
|
|
TextForDigit := TextForDigit + '#' + IntToStr(OrdValue);
|
|
end;
|
|
end;
|
|
else
|
|
MapSegNamesToSegments(ControlItem, Segments);
|
|
end;
|
|
while ControlItem[0] = ';' do
|
|
Inc(ControlItem);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.MapControlItems(var Text: PChar; var Segments: Int64);
|
|
begin
|
|
Inc(Text);
|
|
TextForDigit := TextForDigit + '[';
|
|
while not CharInSet(Text^, [#0, ']']) do
|
|
ControlItemToSegments(Text, Segments);
|
|
if Text^ = ']' then
|
|
begin
|
|
Inc(Text);
|
|
TextForDigit := TextForDigit + ']';
|
|
end;
|
|
if Text[0] = DecimalSeparator then
|
|
HandleDecimalSeparator(Text, Segments);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.MapSimpleText(var Text: PChar; var Segments: Int64);
|
|
begin
|
|
if CharToSegments(Text^, Segments) then
|
|
TextForDigit := TextForDigit + Text^;
|
|
Inc(Text);
|
|
if Text[0] = DecimalSeparator then
|
|
HandleDecimalSeparator(Text, Segments);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.MapSegNamesToSegments(var Text: PChar;
|
|
var Segments: Int64);
|
|
var
|
|
SortedSegNames: TStringList;
|
|
I: Integer;
|
|
begin
|
|
SortedSegNames := TStringList.Create;
|
|
try
|
|
for I := 0 to CurDigit.SegmentCount - 1 do
|
|
SortedSegNames.Add(CurDigit.GetSegmentName(I));
|
|
SortedSegNames.Sort;
|
|
|
|
while not CharInSet(Text[0], [#0, ']', ';']) do
|
|
begin
|
|
I := SortedSegNames.Count - 1;
|
|
while I >= 0 do
|
|
begin
|
|
if AnsiStrLIComp(Text, PChar(SortedSegNames[I]), Length(SortedSegNames[I])) = 0 then
|
|
begin
|
|
if UpdateStates(Segments, 1 shl CurDigit.GetSegmentIndex(SortedSegNames[I])) then
|
|
TextForDigit := TextForDigit + SortedSegNames[I];
|
|
Inc(Text, Length(SortedSegNames[I]));
|
|
Break; // End the for loop
|
|
end;
|
|
Dec(I);
|
|
end;
|
|
if I < 0 then
|
|
Inc(Text);
|
|
if Text[0] = ',' then
|
|
Inc(Text);
|
|
end;
|
|
finally
|
|
FreeAndNil(SortedSegNames);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.PrimMapText(var Text: PChar; var Segments: Int64);
|
|
begin
|
|
case Text^ of
|
|
#0:
|
|
Exit;
|
|
'[':
|
|
MapControlItems(Text, Segments);
|
|
else
|
|
MapSimpleText(Text, Segments);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.Modified;
|
|
begin
|
|
FMappingChanged := True;
|
|
Display.RemapText;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.MapText(var Text: PChar;
|
|
ADigit: TJvCustomSegmentedLEDDigit);
|
|
var
|
|
States: Int64;
|
|
begin
|
|
FCurDigit := ADigit;
|
|
FTextForDigit := '';
|
|
States := 0;
|
|
FSegMapRemoves := False;
|
|
PrimMapText(Text, States);
|
|
CurDigit.SetSegmentStates(States);
|
|
if FTextForDigit = '' then // assume a space was used
|
|
FTextForDigit := ' ';
|
|
CurDigit.UpdateText(FTextForDigit);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.Clear;
|
|
begin
|
|
FillChar(FActiveMapping[#0], SizeOf(FActiveMapping), 0);
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.LoadDefaultMapping;
|
|
var
|
|
resName: AnsiString;
|
|
Stream: TStream;
|
|
begin
|
|
resName := Display.DigitClass.MapperFileID + '_DEFAULT';
|
|
if FindResource(HInstance, PChar(string(resName)), RT_RCDATA) <> 0 then
|
|
begin
|
|
Stream := TResourceStream.Create(HInstance, string(Display.DigitClass.MapperFileID + '_DEFAULT'), RT_RCDATA);
|
|
try
|
|
LoadFromStream(Stream);
|
|
FMappingChanged := False;
|
|
finally
|
|
FreeAndNil(Stream);
|
|
end;
|
|
end
|
|
else
|
|
Clear;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.LoadFromFile(const FileName: string);
|
|
var
|
|
FS: TFileStream;
|
|
begin
|
|
FS := TFileStream.Create(FileName, fmOpenRead + fmShareDenyWrite);
|
|
try
|
|
LoadFromStream(FS);
|
|
finally
|
|
FS.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.LoadFromStream(Stream: TStream);
|
|
var
|
|
OrgPos: Integer;
|
|
Hdr: TSegCharMapHeader;
|
|
begin
|
|
OrgPos := Stream.Position;
|
|
try
|
|
Stream.ReadBuffer(Hdr, SizeOf(Hdr));
|
|
if StrLIComp(Hdr.ID, PAnsiChar(Display.DigitClass.MapperFileID), Length(Display.DigitClass.MapperFileID)) = 0 then
|
|
PrimReadMapping(Hdr, Stream)
|
|
else
|
|
raise EJVCLSegmentedLEDException.CreateRes(@RsEInvalidMappingFile);
|
|
except
|
|
Stream.Position := OrgPos;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.SaveToFile(const FileName: string);
|
|
var
|
|
FS: TFileStream;
|
|
begin
|
|
FS := TFileStream.Create(FileName, fmCreate);
|
|
try
|
|
SaveToStream(FS);
|
|
finally
|
|
FS.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvSegmentedLEDCharacterMapper.SaveToStream(Stream: TStream);
|
|
var
|
|
Hdr: TSegCharMapHeader;
|
|
TmpID: AnsiString;
|
|
MapSize: Byte;
|
|
Chr: AnsiChar;
|
|
TmpDot: Int64;
|
|
TmpComma: Int64;
|
|
begin
|
|
FillChar(Hdr, SizeOf(Hdr), 0);
|
|
TmpID := Display.DigitClass.MapperFileID;
|
|
Move(TmpID[1], Hdr.ID, Length(TmpID));
|
|
Hdr.Flags := MaxSegments;
|
|
MapSize := (Hdr.Flags div 8) + Ord((Hdr.Flags mod 8) <> 0);
|
|
Hdr.Flags := MapSize;
|
|
Hdr.Flags := Hdr.Flags or (16 * Ord(MapToSeparators));
|
|
Hdr.MappedChars := [];
|
|
TmpDot := FActiveMapping['.'];
|
|
TmpComma := FActiveMapping[','];
|
|
if DecimalSeparator <> '.' then
|
|
begin
|
|
FActiveMapping['.'] := TmpComma;
|
|
FActiveMapping[','] := TmpDot;
|
|
end;
|
|
try
|
|
for Chr := #0 to #255 do
|
|
if FActiveMapping[Chr] <> 0 then
|
|
Include(Hdr.MappedChars, Chr);
|
|
Stream.WriteBuffer(Hdr, SizeOf(Hdr));
|
|
for Chr := #0 to #255 do
|
|
if FActiveMapping[Chr] <> 0 then
|
|
Stream.WriteBuffer(FActiveMapping[Chr], MapSize);
|
|
finally
|
|
if DecimalSeparator <> '.' then
|
|
begin
|
|
FActiveMapping['.'] := TmpDot;
|
|
FActiveMapping[','] := TmpComma;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJv7SegmentedLEDDigit } ==============================================
|
|
|
|
procedure TJv7SegmentedLEDDigit.EnableAllSegs;
|
|
begin
|
|
inherited EnableAllSegs;
|
|
UseColon := scuFull;
|
|
end;
|
|
|
|
function TJv7SegmentedLEDDigit.GetUseColon: T7SegColonUsage;
|
|
begin
|
|
Result := FUseColon;
|
|
end;
|
|
|
|
procedure TJv7SegmentedLEDDigit.SetUseColon(Value: T7SegColonUsage);
|
|
begin
|
|
if Value <> UseColon then
|
|
begin
|
|
FUseColon := Value;
|
|
InvalidateRefPoints;
|
|
end;
|
|
end;
|
|
|
|
class function TJv7SegmentedLEDDigit.SegmentCount: Integer;
|
|
begin
|
|
Result := 10;
|
|
end;
|
|
|
|
class function TJv7SegmentedLEDDigit.GetSegmentName(Index: Integer): string;
|
|
begin
|
|
if Index <= 7 then
|
|
Result := inherited GetSegmentName(Index)
|
|
else
|
|
if Index = 8 then
|
|
Result := 'CL'
|
|
else
|
|
if Index = 9 then
|
|
Result := 'CH'
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
class function TJv7SegmentedLEDDigit.GetSegmentIndex(Name: string): Integer;
|
|
begin
|
|
Result := inherited GetSegmentIndex(Name);
|
|
if Result = -1 then
|
|
begin
|
|
Name := UpperCase(Name);
|
|
if Name = 'CL' then
|
|
Result := 8
|
|
else
|
|
if Name = 'CH' then
|
|
Result := 9;
|
|
end;
|
|
end;
|
|
|
|
procedure TJv7SegmentedLEDDigit.RecalcSegments;
|
|
begin
|
|
if UseColon <> scuColonOnly then
|
|
inherited RecalcSegments;
|
|
if UseColon in [scuLowOnly, scuFull, scuColonOnly] then
|
|
CalcCLSeg(8);
|
|
if UseColon in [scuFull, scuColonOnly] then
|
|
CalcCHSeg(9);
|
|
end;
|
|
|
|
class function TJv7SegmentedLEDDigit.MapperFileID: AnsiString;
|
|
begin
|
|
Result := 'SLDCM_7SEG';
|
|
end;
|
|
|
|
procedure TJv7SegmentedLEDDigit.CalcCHSeg(Index: Integer);
|
|
var
|
|
UpperLeftPoint: TPoint;
|
|
begin
|
|
UpperLeftPoint := AngleAdjustPoint(FRefCenterX - DotSize div 2,
|
|
(FRefCenterY - FRefTop) div 2 + FRefTop, SlantAngle);
|
|
SetSegmentRenderInfo(Index, srtCircle,
|
|
[UpperLeftPoint, Point(UpperLeftPoint.X + DotSize, UpperLeftPoint.Y + DotSize)]);
|
|
end;
|
|
|
|
procedure TJv7SegmentedLEDDigit.CalcCLSeg(Index: Integer);
|
|
var
|
|
UpperLeftPoint: TPoint;
|
|
begin
|
|
UpperLeftPoint := AngleAdjustPoint(FRefCenterX - DotSize div 2,
|
|
(FRefBottom - FRefCenterY) div 2 + FRefCenterY - DotSize div 2, SlantAngle);
|
|
SetSegmentRenderInfo(Index, srtCircle,
|
|
[UpperLeftPoint, Point(UpperLeftPoint.X + DotSize, UpperLeftPoint.Y + DotSize)]);
|
|
end;
|
|
|
|
//=== { TJv14SegmentedLEDDigit } ==============================================
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcG1Seg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2, FRefCenterY, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth div 2, FRefCenterY - SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2 - SegmentWidth div 4, FRefCenterY - SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2, FRefCenterY, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2 - SegmentWidth div 4, FRefCenterY + SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth div 2, FRefCenterY + SegmentWidth div 2, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcG2Seg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2, FRefCenterY, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2 + SegmentWidth div 4, FRefCenterY - SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth div 2, FRefCenterY - SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2, FRefCenterY, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth div 2, FRefCenterY + SegmentWidth div 2, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2 + SegmentWidth div 4, FRefCenterY + SegmentWidth div 2, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcHSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing + SegmentWidth, FRefTop + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing + SegmentWidth + SegmentWidth div 2, FRefTop + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing - SegmentWidth div 2, FRefCenterY - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing - SegmentWidth div 2, FRefCenterY - SegmentWidth div 2 - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing - SegmentWidth, FRefCenterY - SegmentWidth div 2 - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing + SegmentWidth, FRefTop + SegmentWidth + SegmentWidth div 4 + Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcISeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefTop + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefCenterY - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX, FRefCenterY - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefCenterY - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefTop + SegmentWidth + Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcJSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefRight - Spacing - SegmentWidth, FRefTop + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing - SegmentWidth - SegmentWidth div 2, FRefTop + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing + SegmentWidth div 2, FRefCenterY - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing + SegmentWidth div 2, FRefCenterY - SegmentWidth div 2 - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing + SegmentWidth, FRefCenterY - SegmentWidth div 2 - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing - SegmentWidth, FRefTop + SegmentWidth + SegmentWidth div 4 + Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcKSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing + SegmentWidth, FRefBottom - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing + SegmentWidth + SegmentWidth div 2, FRefBottom - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing - SegmentWidth div 2, FRefCenterY + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing - SegmentWidth div 2, FRefCenterY + SegmentWidth div 2 + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing - SegmentWidth, FRefCenterY + SegmentWidth div 2 + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing + SegmentWidth, FRefBottom - SegmentWidth - SegmentWidth div 4 - Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcLSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefBottom - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefCenterY + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX, FRefCenterY + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefCenterY + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefBottom - SegmentWidth - Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.CalcMSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefRight - Spacing - SegmentWidth, FRefBottom - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing - SegmentWidth - SegmentWidth div 2, FRefBottom - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing + SegmentWidth div 2, FRefCenterY + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing + SegmentWidth div 2, FRefCenterY + SegmentWidth div 2 + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing + SegmentWidth, FRefCenterY + SegmentWidth div 2 + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing - SegmentWidth, FRefBottom - SegmentWidth - SegmentWidth div 4 - Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
class function TJv14SegmentedLEDDigit.GetSegmentIndex(Name: string): Integer;
|
|
begin
|
|
Result := TextIndex(Name, ['A', 'B', 'C', 'D', 'E', 'F', 'G1', 'G2', 'H', 'I', 'J', 'K', 'L', 'M', 'DP']);
|
|
end;
|
|
|
|
class function TJv14SegmentedLEDDigit.GetSegmentName(Index: Integer): string;
|
|
begin
|
|
if Index = 6 then
|
|
Result := 'G1'
|
|
else
|
|
if Index = 7 then
|
|
Result := 'G2'
|
|
else
|
|
if Index < 6 then
|
|
Result := Chr(Ord('A') + Index)
|
|
else
|
|
if (Index > 7) and (Index < 14) then
|
|
Result := Chr(Ord('A') + Index - 1)
|
|
else
|
|
if Index = 14 then
|
|
Result := 'DP'
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
class function TJv14SegmentedLEDDigit.MapperFileID: AnsiString;
|
|
begin
|
|
Result := 'SLDCM_14SEG';
|
|
end;
|
|
|
|
procedure TJv14SegmentedLEDDigit.RecalcSegments;
|
|
begin
|
|
CalcASeg(0);
|
|
CalcBSeg(1);
|
|
CalcCSeg(2);
|
|
CalcDSeg(3);
|
|
CalcESeg(4);
|
|
CalcFSeg(5);
|
|
CalcG1Seg(6);
|
|
CalcG2Seg(7);
|
|
CalcHSeg(8);
|
|
CalcISeg(9);
|
|
CalcJSeg(10);
|
|
CalcKSeg(11);
|
|
CalcLSeg(12);
|
|
CalcMSeg(13);
|
|
if UseDP then
|
|
CalcDPSeg(14);
|
|
end;
|
|
|
|
class function TJv14SegmentedLEDDigit.SegmentCount: Integer;
|
|
begin
|
|
Result := 15;
|
|
end;
|
|
|
|
//=== { TJv16SegmentedLEDDigit } ===============================================
|
|
|
|
const
|
|
seg16Names: array[0..16] of string = (
|
|
'A1', 'A2', 'B', 'C', 'D1', 'D2', 'E', 'F', 'G1', 'G2', 'H', 'I', 'J', 'K', 'L', 'M', 'DP');
|
|
|
|
procedure TJv16SegmentedLEDDigit.CalcA1Seg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2, FRefTop, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2, FRefTop, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2 - SegmentWidth, FRefTop + SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth, FRefTop + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv16SegmentedLEDDigit.CalcA2Seg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2, FRefTop, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2, FRefTop, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth, FRefTop + SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2 + SegmentWidth, FRefTop + SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv16SegmentedLEDDigit.CalcD1Seg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2, FRefBottom, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2, FRefBottom, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - Spacing div 2 - SegmentWidth, FRefBottom - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefLeft + Spacing div 2 + SegmentWidth, FRefBottom - SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv16SegmentedLEDDigit.CalcD2Seg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2, FRefBottom, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2, FRefBottom, SlantAngle),
|
|
AngleAdjustPoint(FRefRight - Spacing div 2 - SegmentWidth, FRefBottom - SegmentWidth, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + Spacing div 2 + SegmentWidth, FRefBottom - SegmentWidth, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv16SegmentedLEDDigit.CalcISeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX, FRefTop + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefTop + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefCenterY - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX, FRefCenterY - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefCenterY - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefTop + SegmentWidth + Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
procedure TJv16SegmentedLEDDigit.CalcLSeg(Index: Integer);
|
|
begin
|
|
SetSegmentRenderInfo(Index, srtPolygon, [
|
|
AngleAdjustPoint(FRefCenterX, FRefBottom - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefBottom - SegmentWidth - Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX + SegmentWidth div 2, FRefCenterY + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX, FRefCenterY + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefCenterY + SegmentWidth + Spacing, SlantAngle),
|
|
AngleAdjustPoint(FRefCenterX - SegmentWidth div 2, FRefBottom - SegmentWidth - Spacing, SlantAngle)
|
|
]);
|
|
end;
|
|
|
|
class function TJv16SegmentedLEDDigit.GetSegmentIndex(Name: string): Integer;
|
|
begin
|
|
Result := TextIndex(Name, seg16Names);
|
|
end;
|
|
|
|
class function TJv16SegmentedLEDDigit.GetSegmentName(Index: Integer): string;
|
|
begin
|
|
Result := seg16Names[Index];
|
|
end;
|
|
|
|
class function TJv16SegmentedLEDDigit.MapperFileID: AnsiString;
|
|
begin
|
|
Result := 'SLDCM_16SEG';
|
|
end;
|
|
|
|
procedure TJv16SegmentedLEDDigit.RecalcSegments;
|
|
begin
|
|
CalcA1Seg(0);
|
|
CalcA2Seg(1);
|
|
CalcBSeg(2);
|
|
CalcCSeg(3);
|
|
CalcD1Seg(4);
|
|
CalcD2Seg(5);
|
|
CalcESeg(6);
|
|
CalcFSeg(7);
|
|
CalcG1Seg(8);
|
|
CalcG2Seg(9);
|
|
CalcHSeg(10);
|
|
CalcISeg(11);
|
|
CalcJSeg(12);
|
|
CalcKSeg(13);
|
|
CalcLSeg(14);
|
|
CalcMSeg(15);
|
|
if UseDP then
|
|
CalcDPSeg(16);
|
|
end;
|
|
|
|
class function TJv16SegmentedLEDDigit.SegmentCount: Integer;
|
|
begin
|
|
Result := 17;
|
|
end;
|
|
|
|
//=== { initialization and support routines } =================================
|
|
|
|
procedure ModuleUnload(Instance: Longint);
|
|
begin
|
|
UnregisterModuleSegmentedLEDDigitClasses(HMODULE(Instance));
|
|
end;
|
|
|
|
function IdentToUnlitColor(const Ident: string; var Int: Longint): Boolean;
|
|
begin
|
|
Int := TextIndex(Ident, ['clDefaultBackground', 'clDefaultLitColor']);
|
|
Result := Int > -1;
|
|
if Result then
|
|
Inc(Int, clDefaultBackground)
|
|
else
|
|
Result := IdentToColor(Ident, Int);
|
|
end;
|
|
|
|
function UnlitColorToIdent(Int: Longint; var Ident: string): Boolean;
|
|
begin
|
|
Result := True;
|
|
case Int of
|
|
clDefaultBackground:
|
|
Ident := 'clDefaultBackground';
|
|
clDefaultLitColor:
|
|
Ident := 'clDefaultLitColor';
|
|
else
|
|
Result := ColorToIdent(Int, Ident);
|
|
end;
|
|
end;
|
|
|
|
function StringToUnlitColor(const S: string): TUnlitColor;
|
|
begin
|
|
if not IdentToUnlitColor(S, Longint(Result)) then
|
|
Result := StrToInt(S);
|
|
end;
|
|
|
|
function UnlitColorToString(const Color: TUnlitColor): string;
|
|
begin
|
|
if not ColorToIdent(Color, Result) then
|
|
Result := Format('%s%.8x', [HexDisplayPrefix, Color]);
|
|
end;
|
|
|
|
initialization
|
|
{$IFDEF UNITVERSIONING}
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
{$ENDIF UNITVERSIONING}
|
|
AddModuleUnloadProc(ModuleUnload);
|
|
RegisterSegmentedLEDDigitClasses([TJv7SegmentedLEDDigit, TJv14SegmentedLEDDigit, TJv16SegmentedLEDDigit]);
|
|
RegisterIntegerConsts(TypeInfo(TUnlitColor), IdentToUnlitColor, UnlitColorToIdent);
|
|
|
|
finalization
|
|
UnregisterIntegerConsts(TypeInfo(TUnlitColor), IdentToUnlitColor, UnlitColorToIdent);
|
|
UnregisterModuleSegmentedLEDDigitClasses(HInstance);
|
|
FreeAndNil(GDigitClassList);
|
|
RemoveModuleUnloadProc(ModuleUnload);
|
|
{$IFDEF UNITVERSIONING}
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|