1221 lines
41 KiB
ObjectPascal
1221 lines
41 KiB
ObjectPascal
{****************************************************
|
|
This file is part of the Eye Candy Controls (EC-C)
|
|
|
|
Copyright (C) 2013 Vojtěch Čihák, Czech Republic
|
|
|
|
This library is free software.
|
|
|
|
See the file COPYING.LGPL.txt,
|
|
included in this distribution,
|
|
for details about the license.
|
|
****************************************************}
|
|
|
|
unit ECScale;
|
|
{$mode objfpc}{$H+}
|
|
|
|
//{$DEFINE DBGSCALE} {don't remove, just comment}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Controls, ECTypes, Graphics,
|
|
{$IFDEF DBGSCALE} LCLProc, {$ENDIF} LCLType, Math, Themes;
|
|
|
|
type
|
|
{$PACKENUM 2}
|
|
TScaleType = (estLinear, estLogarithmic);
|
|
TTickAlign = (etaOuter, etaInner, etaCenter);
|
|
TTickSize = (etsShort, etsMiddle, etsLong);
|
|
TTickMetrics = record
|
|
Pos: Integer;
|
|
Size: TTickSize;
|
|
end;
|
|
TTicksVisible = (etvNone, etvLongOnly, etvLongShort, etvAll);
|
|
TValueDisplay = (evdNormal, evdTopLeft, evdBottomRight, evdTopLeftInside,
|
|
evdBttmRightInside, evdCompactTopLeft, evdCompactBttmRight);
|
|
TScaleValueFormat = (esvfAutoRound, esvfFixedRound, esvfSmartRound, esvfExponential, esvfHexadecimal,
|
|
esvfMarkHexadec, esvfOctal, esvfBinary, esvfDate, esvfTime, esvfText);
|
|
|
|
const
|
|
cDefTickAlign = etaOuter;
|
|
cDefTickIndent = 5;
|
|
cDefTickLength = 20;
|
|
cDefTickVisible = etvAll;
|
|
cDefValFormat = esvfAutoRound;
|
|
cDefValIndent = 5;
|
|
cDefValVisible = evvAll;
|
|
|
|
type
|
|
{ TCustomECScale }
|
|
TCustomECScale = class(TPersistent)
|
|
private
|
|
FMax: Double;
|
|
FMin: Double;
|
|
FOnPrepareValue: TOnPrepareValue;
|
|
FText: TStrings;
|
|
procedure SetCorrection(AValue: Double);
|
|
procedure SetDateTimeFormat(const AValue: string);
|
|
procedure SetDigits(const AValue: SmallInt);
|
|
procedure SetFontOrientation(const AValue: Integer);
|
|
procedure SetLogarithmBase(const AValue: Double);
|
|
procedure SetMax(const AValue: Double);
|
|
procedure SetMin(const AValue: Double);
|
|
procedure SetScaleType(const AValue: TScaleType);
|
|
procedure SetText(const AValue: TStrings);
|
|
procedure SetTickAlign(const AValue: TTickAlign);
|
|
procedure SetTickColor(const AValue: TColor);
|
|
procedure SetTickDesign(const AValue: TTickDesign);
|
|
procedure SetTickIndent(const AValue: SmallInt);
|
|
procedure SetTickLength(const AValue: SmallInt);
|
|
procedure SetTickLongValue(const AValue: Double);
|
|
procedure SetTickMiddleValue(const AValue: Double);
|
|
procedure SetTickShortValue(const AValue: Double);
|
|
procedure SetTickVisible(const AValue: TTicksVisible);
|
|
procedure SetValueDisplay(const AValue: TValueDisplay);
|
|
procedure SetValueFormat(const AValue: TScaleValueFormat);
|
|
procedure SetValueIndent(const AValue: SmallInt);
|
|
procedure SetValueShift(const AValue: SmallInt);
|
|
procedure SetValueVisible(const AValue: TValuesVisibility);
|
|
protected
|
|
FCorrection: Double;
|
|
FDateTimeFormat: string;
|
|
FDigits: SmallInt;
|
|
FFontOrientation: Integer;
|
|
FLogarithmBase: Double;
|
|
FScaleType: TScaleType;
|
|
FTickAlign: TTickAlign;
|
|
FTickColor: TColor;
|
|
FTickDesign: TTickDesign;
|
|
FTickIndent: SmallInt;
|
|
FTickLength: SmallInt;
|
|
FTickLongValue: Double;
|
|
FTickMiddleValue: Double;
|
|
FTickShortValue: Double;
|
|
FTickVisible: TTicksVisible;
|
|
FValueDisplay: TValueDisplay;
|
|
FValueFormat: TScaleValueFormat;
|
|
FValueIndent: SmallInt;
|
|
FValueShift: SmallInt;
|
|
FValueVisible: TValuesVisibility;
|
|
protected
|
|
LengthPx, MaxL, MinL: Integer;
|
|
Reversed: Boolean;
|
|
Parent: TControl;
|
|
procedure CalcTicksValuesLinear(ALength: Integer; AReversed: Boolean);
|
|
procedure CalcTicksValuesLogarithmic(ALength: Integer; AReversed: Boolean);
|
|
function GetStringValue(AIndex: Integer): string; overload;
|
|
procedure Redraw; virtual;
|
|
procedure RecalcRedraw; virtual;
|
|
public
|
|
DTFormat: TFormatSettings;
|
|
OnRecalcRedraw: TObjectMethod;
|
|
OnRedraw: TObjectMethod;
|
|
TickArray: array of TTickMetrics;
|
|
UpdateCount: Integer;
|
|
ValueArray: array of Double;
|
|
constructor Create(AParent: TControl);
|
|
destructor Destroy; override;
|
|
procedure BeginUpdate;
|
|
procedure CalcTickPosAndValues(ALength: Integer; AReversed: Boolean);
|
|
procedure Draw(ACanvas: TCanvas; ATicks, AValues: Boolean; AScalePos: TObjectPos;
|
|
ATickStart: TPoint; AExtraValues: array of Double); overload;
|
|
procedure Draw(ACanvas: TCanvas; ATicks, AValues: Boolean;
|
|
AScalePos: TObjectPos; AColor3DDark, AColor3DLight: TColor;
|
|
ATickStart: TPoint; AExtraValues: array of Double);
|
|
procedure EndUpdate;
|
|
function GetPreferredSize(ACanvas: TCanvas; AHorizontal: Boolean;
|
|
ATicks: Boolean = True; AValues: Boolean = True): Integer;
|
|
function GetPreferredValuesHeight(ACanvas: TCanvas): Integer;
|
|
function GetPreferredValuesWidth(ACanvas: TCanvas): Integer;
|
|
function GetStringMax: string;
|
|
function GetStringMin: string;
|
|
function GetStringPosition(APosition: Double): string; overload;
|
|
function GetStringPosition(APosition: Double; ARound: SmallInt): string; overload;
|
|
function GetStringValue(AValue: Double; ARound: Integer): string; overload;
|
|
function GetTextSize(ACanvas: TCanvas; AStrVal: string; AHorizontal: Boolean): Integer;
|
|
property Correction: Double read FCorrection write SetCorrection;
|
|
property DateTimeFormat: string read FDateTimeFormat write SetDateTimeFormat;
|
|
property Digits: SmallInt read FDigits write SetDigits default 0;
|
|
property FontOrientation: Integer read FFontOrientation write SetFontOrientation default 0;
|
|
property LogarithmBase: Double read FLogarithmBase write SetLogarithmBase;
|
|
property Max: Double read FMax write SetMax;
|
|
property Min: Double read FMin write SetMin;
|
|
property ScaleType: TScaleType read FScaleType write SetScaleType default estLinear;
|
|
property Text: TStrings read FText write SetText;
|
|
property TickAlign: TTickAlign read FTickAlign write SetTickAlign default cDefTickAlign;
|
|
property TickColor: TColor read FTickColor write SetTickColor default clDefault;
|
|
property TickDesign: TTickDesign read FTickDesign write SetTickDesign default etdSimple;
|
|
property TickIndent: SmallInt read FTickIndent write SetTickIndent default cDefTickIndent;
|
|
property TickLength: SmallInt read FTickLength write SetTickLength default cDefTickLength;
|
|
property TickLongValue: Double read FTickLongValue write SetTickLongValue;
|
|
property TickMiddleValue: Double read FTickMiddleValue write SetTickMiddleValue;
|
|
property TickShortValue: Double read FTickShortValue write SetTickShortValue;
|
|
property TickVisible: TTicksVisible read FTickVisible write SetTickVisible default cDefTickVisible;
|
|
property ValueDisplay: TValueDisplay read FValueDisplay write SetValueDisplay default evdNormal;
|
|
property ValueFormat: TScaleValueFormat read FValueFormat write SetValueFormat default cDefValFormat;
|
|
property ValueIndent: SmallInt read FValueIndent write SetValueIndent default cDefValIndent;
|
|
property ValueShift: SmallInt read FValueShift write SetValueShift default 0;
|
|
property ValueVisible: TValuesVisibility read FValueVisible write SetValueVisible default cDefValVisible;
|
|
property OnPrepareValue: TOnPrepareValue read FOnPrepareValue write FOnPrepareValue;
|
|
end;
|
|
|
|
{ TECScale }
|
|
TECScale = class(TCustomECScale)
|
|
published
|
|
property DateTimeFormat;
|
|
property Digits;
|
|
{ property FontOrientation; }
|
|
property LogarithmBase;
|
|
property Max;
|
|
property Min;
|
|
property ScaleType;
|
|
property Text;
|
|
property TickAlign;
|
|
property TickColor;
|
|
property TickDesign;
|
|
property TickIndent;
|
|
property TickLength;
|
|
property TickLongValue;
|
|
property TickMiddleValue;
|
|
property TickShortValue;
|
|
property TickVisible;
|
|
property ValueDisplay;
|
|
property ValueFormat;
|
|
property ValueIndent;
|
|
property ValueShift;
|
|
property ValueVisible;
|
|
property OnPrepareValue;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TCustomECScale }
|
|
|
|
constructor TCustomECScale.Create(AParent: TControl);
|
|
begin
|
|
inherited Create;
|
|
Parent:=AParent;
|
|
DTFormat:=DefaultFormatSettings;
|
|
FCorrection:=0;
|
|
FDateTimeFormat:='hh:nn:ss';
|
|
DTFormat.LongTimeFormat:=FDateTimeFormat;
|
|
FLogarithmBase:=10;
|
|
FMin:=0;
|
|
FMax:=100;
|
|
FText:=TStringList.Create;
|
|
FTickAlign:=cDefTickAlign;
|
|
FTickColor:=clDefault;
|
|
FTickIndent:=cDefTickIndent;
|
|
FTickLength:=cDefTickLength;
|
|
FTickShortValue:=1;
|
|
FTickMiddleValue:=5;
|
|
FTickLongValue:=10;
|
|
FTickVisible:=cDefTickVisible;
|
|
FValueFormat:=cDefValFormat;
|
|
FValueIndent:=cDefValIndent;
|
|
FValueVisible:=cDefValVisible;
|
|
end;
|
|
|
|
destructor TCustomECScale.Destroy;
|
|
begin
|
|
FreeAndNil(FText);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TCustomECScale.BeginUpdate;
|
|
begin
|
|
inc(UpdateCount);
|
|
end;
|
|
|
|
procedure TCustomECScale.CalcTickPosAndValues(ALength: Integer; AReversed: Boolean);
|
|
begin
|
|
LengthPx:=ALength;
|
|
Reversed:=AReversed;
|
|
SetLength(TickArray, 0);
|
|
if (TickVisible>etvNone) or (ValueVisible>evvNone) then
|
|
case ScaleType of
|
|
estLinear: CalcTicksValuesLinear(ALength, AReversed);
|
|
estLogarithmic: CalcTicksValuesLogarithmic(ALength, AReversed);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomECScale.CalcTicksValuesLinear(ALength: Integer; AReversed: Boolean);
|
|
var aDistPx, aShift, pxlsPerUnit: Double;
|
|
AMinL, AMaxL, i, j, aPos, myPos, lLim, hLim, tMin, tMax: Integer;
|
|
bAddedTick, bTickInserted: Boolean;
|
|
|
|
function GetValueMax(ATickValue: Double): Integer;
|
|
var aCorrection, aFrac, aHighest: Double;
|
|
begin
|
|
aHighest:=Max/ATickValue;
|
|
aFrac:=frac(aHighest);
|
|
aCorrection:=Correction/ATickValue;
|
|
Result:=trunc(aHighest);
|
|
if aFrac>(1-aCorrection) then inc(Result)
|
|
else if aFrac<-aCorrection then dec(Result);
|
|
end;
|
|
|
|
function GetValueMin(ATickValue: Double): Integer;
|
|
var aCorrection, aFrac, aLowest: Double;
|
|
begin
|
|
aLowest:=Min/ATickValue;
|
|
aFrac:=frac(aLowest);
|
|
aCorrection:=Correction/ATickValue;
|
|
Result:=trunc(aLowest);
|
|
if aFrac>aCorrection then
|
|
begin
|
|
inc(Result);
|
|
aShift:=1-abs(aFrac);
|
|
end else
|
|
begin
|
|
if aFrac<(-1+aCorrection) then
|
|
begin
|
|
dec(Result);
|
|
aShift:=0;
|
|
end else
|
|
aShift:=abs(aFrac);
|
|
end;
|
|
end;
|
|
begin
|
|
pxlsPerUnit:=(ALength-0.99)/(Max-Min);
|
|
aDistPx:=TickShortValue*pxlsPerUnit; { distance between Short Ticks }
|
|
if (TickVisible>etvLongOnly) and (aDistPx>0.5) then
|
|
begin { Calc. Small Ticks }
|
|
tMin:=GetValueMin(TickShortValue);
|
|
tMax:=GetValueMax(TickShortValue);
|
|
SetLength(TickArray, tMax-tMin+1);
|
|
for i:=0 to tMax-tMin do
|
|
begin
|
|
TickArray[i].Pos:=round((aShift+i)*aDistPx);
|
|
TickArray[i].Size:=etsShort;
|
|
end;
|
|
end;
|
|
bAddedTick:=False;
|
|
aDistPx:=TickMiddleValue*pxlsPerUnit; { distance between Middle Ticks }
|
|
if (TickVisible=etvAll) and (aDistPx>0.5) then
|
|
begin { Calc. Middle Ticks }
|
|
lLim:=0;
|
|
hLim:=trunc(TickMiddleValue/TickShortValue);
|
|
tMin:=GetValueMin(TickMiddleValue);
|
|
tMax:=GetValueMax(TickMiddleValue);
|
|
for i:=0 to tMax-tMin do
|
|
begin
|
|
aPos:=trunc((aShift+i)*aDistPx);
|
|
bTickInserted:=False;
|
|
for j:=lLim to high(TickArray) do
|
|
begin
|
|
if (TickArray[j].Pos=aPos) or (TickArray[j].Pos=(aPos+1)) then
|
|
begin
|
|
TickArray[j].Size:=etsMiddle;
|
|
bTickInserted:=True;
|
|
lLim:=j+hLim;
|
|
break;
|
|
end;
|
|
end;
|
|
if not bTickInserted then
|
|
begin
|
|
SetLength(TickArray, high(TickArray)+2);
|
|
TickArray[high(TickArray)].Pos:=aPos;
|
|
TickArray[high(TickArray)].Size:=etsMiddle;
|
|
bAddedTick:=True;
|
|
end;
|
|
end;
|
|
end;
|
|
{ Calc. Long Ticks }
|
|
aDistPx:=TickLongValue*pxlsPerUnit; { distance between Long Ticks }
|
|
if aDistPx>0.5 then
|
|
begin
|
|
AMinL:=high(Integer);
|
|
AMaxL:=low(Integer);
|
|
lLim:=0;
|
|
hLim:=trunc(TickLongValue/TickShortValue);
|
|
tMin:=GetValueMin(TickLongValue);
|
|
tMax:=GetValueMax(TickLongValue);
|
|
for i:=0 to tMax-tMin do
|
|
begin
|
|
aPos:=trunc((aShift+i)*aDistPx);
|
|
bTickInserted:=False;
|
|
for j:=lLim to high(TickArray) do
|
|
begin
|
|
if (TickArray[j].Pos=aPos) or (TickArray[j].Pos=(aPos+1)) then
|
|
begin
|
|
myPos:=TickArray[j].Pos;
|
|
TickArray[j].Size:=etsLong;
|
|
bTickInserted:=True;
|
|
if not bAddedTick then lLim:=j+hLim; { ensure to search whole array when at least one tick was added }
|
|
break;
|
|
end;
|
|
end;
|
|
if not bTickInserted then
|
|
begin
|
|
SetLength(TickArray, high(TickArray)+2);
|
|
TickArray[high(TickArray)].Pos:=aPos;
|
|
TickArray[high(TickArray)].Size:=etsLong;
|
|
myPos:=aPos;
|
|
end;
|
|
if myPos<AMinL then AMinL:=myPos;
|
|
if myPos>AMaxL then AMaxL:=myPos;
|
|
end;
|
|
end else
|
|
begin
|
|
tMin:=0;
|
|
tMax:=0;
|
|
end;
|
|
if AReversed then
|
|
begin
|
|
MaxL:=LengthPx-AMinL;
|
|
MinL:=LengthPx-AMaxL;
|
|
end else
|
|
begin
|
|
MaxL:=AMaxL;
|
|
MinL:=AMinL;
|
|
end;
|
|
if ValueVisible>evvNone then
|
|
begin
|
|
SetLength(ValueArray, tMax-tMin+1);
|
|
for i:=0 to tMax-tMin do
|
|
ValueArray[i]:=TickLongValue*(i+tMin);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomECScale.CalcTicksValuesLogarithmic(ALength: Integer; AReversed: Boolean);
|
|
var aHelp, aMin, aMax, fracMin, pxlsPerUnit: Double;
|
|
aMinHasFrac: SmallInt;
|
|
aHiTick, aMiddlePos, i, j, k, aLogBaseMinus1, lowTicks, hiTicks, truncMin, truncMax: Integer;
|
|
bMiddleMark: Boolean;
|
|
const caTick: array[False..True] of TTickSize = (etsShort, etsMiddle);
|
|
begin
|
|
aLogBaseMinus1:=trunc(LogarithmBase)-1;
|
|
aMin:=Min;
|
|
aMax:=Max;
|
|
if aMin>0
|
|
then aMin:=logn(LogarithmBase, aMin)
|
|
else aMin:=0;
|
|
truncMin:=trunc(AMin);
|
|
fracMin:=frac(AMin);
|
|
if fracMin<0.0 then dec(truncMin);
|
|
if aMax>0
|
|
then aMax:=logn(LogarithmBase, aMax)
|
|
else aMax:=0;
|
|
truncMax:=trunc(AMax);
|
|
if frac(aMax)<0.0 then dec(truncMax);
|
|
if aMin<aMax then
|
|
begin
|
|
pxlsPerUnit:=(ALength-0.99)/(aMax-aMin);
|
|
if abs(fracMin)>0.0
|
|
then aMinHasFrac:=1
|
|
else aMinHasFrac:=0;
|
|
if TickVisible>etvLongOnly then
|
|
begin { All Ticks }
|
|
hiTicks:=trunc(Max/power(LogarithmBase, truncMax));
|
|
aHelp:=Min/power(LogarithmBase, truncMin);
|
|
lowTicks:=trunc(LogarithmBase)-trunc(aHelp);
|
|
if frac(aHelp)>0.0 then dec(lowTicks);
|
|
if lowTicks>=aLogBaseMinus1 then lowTicks:=0;
|
|
j:=truncMax-truncMin;
|
|
if (lowTicks>0) or (frac(aHelp)>0.0) then dec(j);
|
|
if j>=0 then
|
|
begin
|
|
SetLength(TickArray, aLogBaseMinus1*j+lowTicks+hiTicks);
|
|
aHiTick:=aLogBaseMinus1;
|
|
end else
|
|
begin
|
|
if frac(AHelp)=0.0 then j:=1 else j:=0;
|
|
SetLength(TickArray, hiTicks+j-trunc(aHelp));
|
|
aHiTick:=hiTicks;
|
|
end;
|
|
SetLength(ValueArray, truncMax-truncMin+1-aMinHasFrac);
|
|
aHelp:=fracMin;
|
|
if aHelp<0 then aHelp:=1+aHelp;
|
|
bMiddleMark:=(TickVisible=etvAll) and (frac(LogarithmBase)=0.0) and (trunc(LogarithmBase) mod 2 =0);
|
|
aMiddlePos:=trunc(LogarithmBase) div 2;
|
|
if aMinHasFrac=1 then
|
|
begin { Small ticks in front of the very first long tick }
|
|
lowTicks:=trunc(LogarithmBase)-lowTicks;
|
|
for j:=lowTicks to aHiTick do
|
|
begin
|
|
k:=j-lowTicks;
|
|
TickArray[k].Pos:=round((-aHelp+logn(LogarithmBase, j))*pxlsPerUnit);
|
|
TickArray[k].Size:=caTick[bMiddleMark and (j=aMiddlePos)];
|
|
end;
|
|
end;
|
|
i:=0;
|
|
if lowTicks>0 then lowTicks:=trunc(LogarithmBase)-lowTicks;
|
|
while i<(truncMax-truncMin-aMinHasFrac) do
|
|
begin
|
|
TickArray[lowTicks+i*aLogBaseMinus1].Pos:=round((abs(aMinHasFrac-aHelp)+i)*pxlsPerUnit);
|
|
TickArray[lowTicks+i*aLogBaseMinus1].Size:=etsLong;
|
|
for j:=2 to aLogBaseMinus1 do { in the middle }
|
|
begin
|
|
k:=lowTicks+i*aLogBaseMinus1+j-1;
|
|
TickArray[k].Pos:=TickArray[lowTicks+i*aLogBaseMinus1].Pos+round(logn(LogarithmBase, j)*pxlsPerUnit);
|
|
TickArray[k].Size:=caTick[bMiddleMark and (j=aMiddlePos)];
|
|
end;
|
|
inc(i);
|
|
end;
|
|
if length(ValueArray)>0 then
|
|
begin
|
|
TickArray[lowTicks+i*aLogBaseMinus1].Pos:=round((abs(aMinHasFrac-aHelp)+i)*pxlsPerUnit);
|
|
TickArray[lowTicks+i*aLogBaseMinus1].Size:=etsLong;
|
|
for j:=2 to hiTicks do { in the end }
|
|
begin
|
|
k:=lowTicks+i*aLogBaseMinus1+j-1;
|
|
TickArray[k].Pos:=TickArray[lowTicks+i*aLogBaseMinus1].Pos+round(logn(LogarithmBase, j)*pxlsPerUnit);
|
|
TickArray[k].Size:=caTick[bMiddleMark and (j=aMiddlePos)];
|
|
end;
|
|
MinL:=TickArray[lowTicks].Pos;
|
|
MaxL:=TickArray[lowTicks+i*aLogBaseMinus1].Pos;
|
|
end;
|
|
end else
|
|
begin { LongTicks only }
|
|
aHelp:=Min/power(LogarithmBase, truncMin);
|
|
j:=truncMax-truncMin;
|
|
SetLength(ValueArray, j+1-aMinHasFrac);
|
|
if j>=0
|
|
then SetLength(TickArray, j+1-aMinHasFrac)
|
|
else
|
|
begin
|
|
if frac(AHelp)=0.0
|
|
then j:=1
|
|
else j:=0;
|
|
SetLength(TickArray, j-trunc(aHelp));
|
|
end;
|
|
aHelp:=fracMin;
|
|
if aHelp<0 then aHelp:=1+aHelp;
|
|
i:=0;
|
|
k:=truncMax-truncMin-aMinHasFrac;
|
|
while i<=k do
|
|
begin
|
|
TickArray[i].Pos:=round((abs(aMinHasFrac-aHelp)+i)*pxlsPerUnit);
|
|
TickArray[i].Size:=etsLong;
|
|
inc(i);
|
|
end;
|
|
MinL:=TickArray[0].Pos;
|
|
dec(i);
|
|
MaxL:=TickArray[i].Pos;
|
|
end;
|
|
if not AReversed then
|
|
for i:=0 to high(ValueArray) do
|
|
ValueArray[i]:=power(LogarithmBase, truncMin+i+aMinHasFrac)
|
|
else
|
|
begin
|
|
MaxL:=LengthPx-MaxL;
|
|
MinL:=LengthPx-MinL;
|
|
j:=high(ValueArray);
|
|
for i:=0 to j do
|
|
ValueArray[j-i]:=power(LogarithmBase, truncMin+i+aMinHasFrac);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomECScale.Draw(ACanvas: TCanvas; ATicks, AValues: Boolean;
|
|
AScalePos: TObjectPos; ATickStart: TPoint; AExtraValues: array of Double);
|
|
begin
|
|
Draw(ACanvas, ATicks, AValues, AScalePos, clDefault, clDefault, ATickStart, AExtraValues);
|
|
end;
|
|
|
|
procedure TCustomECScale.Draw(ACanvas: TCanvas; ATicks, AValues: Boolean; AScalePos: TObjectPos;
|
|
AColor3DDark, AColor3DLight: TColor; ATickStart: TPoint; AExtraValues: array of Double);
|
|
var aTLStart, aTLEnd, aTMStart, aTMEnd, aTSStart, aTSEnd: Integer; AStart: Integer;
|
|
{$IFDEF DBGSCALE} td: TDateTime; {$ENDIF}
|
|
|
|
procedure CalcTickPoints(AEdge, ARight: Integer);
|
|
var aTLSize, aTMSize, aTSSize: Integer;
|
|
begin { Calculates Start end End points of Ticks }
|
|
aTLSize:=TickLength;
|
|
if FValueDisplay<=evdBottomRight then
|
|
begin { evdNormal, evdTopLeft, evdBottomRight }
|
|
aTMSize:=round(aTLSize*0.7);
|
|
aTSSize:=round(aTLSize*0.4);
|
|
end else
|
|
begin { evdTopLeftInside, evdBttmRightInside, evdCompactTopLeft, evdCompactBttmRight }
|
|
aTMSize:=round(aTLSize*0.5);
|
|
aTSSize:=round(aTLSize*0.3);
|
|
end;
|
|
aTLEnd:=AEdge+ARight*TickIndent;
|
|
aTLStart:=aTLEnd+ARight*aTLSize;
|
|
case TickAlign of
|
|
etaOuter:
|
|
begin
|
|
aTMStart:=aTLStart;
|
|
aTSStart:=aTLStart;
|
|
aTMEnd:=aTMStart-ARight*aTMSize;
|
|
aTSEnd:=aTSStart-ARight*aTSSize;
|
|
end;
|
|
etaInner:
|
|
begin
|
|
aTMEnd:=aTLEnd;
|
|
aTSEnd:=aTLEnd;
|
|
aTMStart:=aTMEnd+ARight*aTMSize;
|
|
aTSStart:=aTSEnd+ARight*aTSSize;
|
|
end;
|
|
etaCenter:
|
|
begin
|
|
aTMEnd:=aTLEnd+ARight*(aTLSize-aTMSize) div 2;
|
|
aTMStart:=aTMEnd+ARight*aTMSize;
|
|
aTSEnd:=aTLEnd+ARight*(aTLSize-aTSSize) div 2;
|
|
aTSStart:=aTSEnd+ARight*aTSSize;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure DrawTicks;
|
|
var aTickColor: TColor;
|
|
|
|
procedure nDrawTicks(AOffSet: Integer);
|
|
var aPos, i: Integer;
|
|
begin
|
|
if not Reversed then AOffSet:=AStart+AOffSet
|
|
else AOffSet:=LengthPx+AOffSet+AStart-1;
|
|
if AScalePos in [eopTop, eopBottom] then
|
|
begin
|
|
for i:=0 to high(TickArray) do
|
|
begin
|
|
if not Reversed then aPos:=AOffSet+TickArray[i].Pos
|
|
else aPos:=AOffSet-TickArray[i].Pos;;
|
|
case TickArray[i].Size of
|
|
etsShort: ACanvas.Line(aPos, aTSStart, aPos, aTSEnd);
|
|
etsMiddle: ACanvas.Line(aPos, aTMStart, aPos, aTMEnd);
|
|
etsLong: ACanvas.Line(aPos, aTLStart, aPos, aTLEnd);
|
|
end;
|
|
end;
|
|
end else
|
|
begin
|
|
for i:=0 to high(TickArray) do
|
|
begin
|
|
if not Reversed then aPos:=AOffSet+TickArray[i].Pos
|
|
else aPos:=AOffSet-TickArray[i].Pos;
|
|
case TickArray[i].Size of
|
|
etsShort: ACanvas.Line(aTSStart, aPos, aTSEnd, aPos);
|
|
etsMiddle: ACanvas.Line(aTMStart, aPos, aTMEnd, aPos);
|
|
etsLong: ACanvas.Line(aTLStart, aPos, aTLEnd, aPos);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
with ACanvas do
|
|
begin
|
|
Pen.Style:=psSolid;
|
|
aTickColor:=GetColorResolvingDefault(TickColor, clBtnText);
|
|
if not Parent.IsEnabled then
|
|
if TickDesign<etd3DLowered then
|
|
begin
|
|
aTickColor:=GetMergedColor(aTickColor, Pixels[Width div 2, Height div 2], 0.45);
|
|
end else
|
|
begin
|
|
AColor3DDark:=GetMergedColor(AColor3DDark, Pixels[Width div 2, Height div 2], 0.67);
|
|
AColor3DLight:=GetMergedColor(AColor3DLight, Pixels[Width div 2, Height div 2], 0.67);
|
|
end;
|
|
case TickDesign of
|
|
etdSimple:
|
|
begin
|
|
Pen.Color:=aTickColor;
|
|
nDrawTicks(0);
|
|
end;
|
|
etdThick:
|
|
begin
|
|
Pen.Color:=aTickColor;
|
|
nDrawTicks(-1);
|
|
nDrawTicks(0);
|
|
end;
|
|
etd3DLowered:
|
|
begin
|
|
Pen.Color:=AColor3DLight;
|
|
nDrawTicks(1);
|
|
Pen.Color:=AColor3DDark;
|
|
nDrawTicks(0);
|
|
end;
|
|
etd3DRaised:
|
|
begin
|
|
Pen.Color:=AColor3DLight;
|
|
nDrawTicks(-1);
|
|
Pen.Color:=AColor3DDark;
|
|
nDrawTicks(0);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure DrawValues; { ARight: -1..TopLeft, 1.. BottomRight }
|
|
var i, lV, valueTL, valueBR: Integer;
|
|
aDetails: TThemedElementDetails;
|
|
aFontColor: TColor;
|
|
cosPi1800, sinPi1800, lHelp: Double;
|
|
strVal: string;
|
|
aRect: TRect;
|
|
aValueVisible: TValuesVisibility;
|
|
|
|
function GetTopLeftPos: Integer;
|
|
begin
|
|
with ACanvas do
|
|
if AScalePos in [eopLeft, eopRight]
|
|
then Result:=round(cosPi1800*TextWidth(strVal)+sinPi1800*TextHeight(strVal))
|
|
else Result:=round(sinPi1800*TextWidth(strVal)+cosPi1800*TextHeight(strVal));
|
|
end;
|
|
|
|
function GetValuePos: Integer;
|
|
var c: Char;
|
|
h: SmallInt;
|
|
begin
|
|
with ACanvas do
|
|
if AScalePos in [eopLeft, eopRight] then
|
|
case ValueDisplay of { Vertical }
|
|
evdNormal: Result:=-round(cosPi1800*(TextHeight(strVal) div 2)+sinPi1800*(TextWidth(strVal) div 2));
|
|
evdTopLeft, evdTopLeftInside: Result:=-round(cosPi1800*TextHeight(strVal)+sinPi1800*TextWidth(strVal));
|
|
evdCompactTopLeft:
|
|
begin
|
|
Result:=0;
|
|
h:=TextHeight('9');
|
|
for c in strVal do
|
|
if not (c=FormatSettings.DecimalSeparator)
|
|
then dec(Result, h)
|
|
else dec(Result, h div 2);
|
|
inc(Result, length(strVal));
|
|
end;
|
|
otherwise Result:=1;
|
|
end else
|
|
case ValueDisplay of { Horizontal }
|
|
evdNormal: Result:=-round(sinPi1800*(TextHeight(strVal) div 2)+cosPi1800*(TextWidth(strVal) div 2));
|
|
evdTopLeft, evdTopLeftInside, evdCompactTopLeft: Result:=-round(sinPi1800*TextHeight(strVal)+cosPi1800*TextWidth(strVal));
|
|
otherwise Result:=1;
|
|
end;
|
|
end;
|
|
|
|
procedure DrawValue;
|
|
var aFlags: Cardinal;
|
|
aValueShift: Integer;
|
|
|
|
procedure nDrawValue(AValue: Integer);
|
|
begin
|
|
if AScalePos in [eopLeft, eopRight] then aRect.Left:=AValue else aRect.Top:=AValue;
|
|
ThemeServices.DrawText(ACanvas, aDetails, strVal, aRect, aFlags, 0);
|
|
end;
|
|
|
|
procedure nDrawValueSplitted(AValue: Integer); { for evdCompactTopLeft & evdCompactBttmRight }
|
|
var c: Char;
|
|
h: Integer;
|
|
begin
|
|
aRect.Left:=AValue;
|
|
h:=ACanvas.TextHeight('9')-1;
|
|
for c in strVal do
|
|
begin
|
|
if c=FormatSettings.DecimalSeparator then dec(aRect.Top, h div 2);
|
|
ThemeServices.DrawText(ACanvas, aDetails, c, aRect, aFlags, 0);
|
|
inc(aRect.Top, h);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if ValueDisplay in [evdTopLeft, evdTopLeftInside, evdCompactTopLeft]
|
|
then aValueShift:=-ValueShift
|
|
else aValueShift:=ValueShift;
|
|
aFlags:=DT_NOPREFIX or DT_SINGLELINE;
|
|
case AScalePos of
|
|
eopTop:
|
|
begin
|
|
aRect.Left:=lV+aValueShift;
|
|
nDrawValue(valueTL-GetTopLeftPos);
|
|
end;
|
|
eopRight:
|
|
begin
|
|
aRect.Top:=lV+aValueShift;
|
|
if ValueDisplay<evdCompactTopLeft
|
|
then nDrawValue(valueBR)
|
|
else nDrawValueSplitted(valueBR);
|
|
end;
|
|
eopBottom:
|
|
begin
|
|
aRect.Left:=lV+aValueShift;
|
|
nDrawValue(valueBR)
|
|
end;
|
|
eopLeft:
|
|
begin
|
|
aRect.Top:=lV+aValueShift;
|
|
if ValueDisplay<evdCompactTopLeft
|
|
then nDrawValue(valueTL-GetTopLeftPos)
|
|
else nDrawValueSplitted(valueTL);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
aDetails:=ThemeServices.GetElementDetails(caThemedContent[caItemState[Parent.IsEnabled]]);
|
|
aRect.Right:=ACanvas.Width;
|
|
aRect.Bottom:=ACanvas.Height;
|
|
aValueVisible:=ValueVisible;
|
|
case AScalePos of
|
|
eopTop:
|
|
if ATicks then
|
|
case ValueDisplay of
|
|
evdNormal, evdTopLeft, evdBottomRight: valueTL:=aTLStart-ValueIndent+2;
|
|
otherwise
|
|
if TickAlign=etaInner
|
|
then valueTL:=aTLStart-ValueIndent+ACanvas.TextHeight('1,9')-1
|
|
else valueTL:=aTLStart-ValueIndent+2;
|
|
end else
|
|
valueTL:=ATickStart.Y-ValueIndent;
|
|
eopRight:
|
|
if ATicks then
|
|
case ValueDisplay of
|
|
evdNormal, evdTopLeft, evdBottomRight: valueBR:=aTLStart+ValueIndent+1;
|
|
otherwise
|
|
case TickAlign of
|
|
etaOuter: valueBR:=aTLStart+ValueIndent+1;
|
|
etaInner: valueBR:=aTLStart+ValueIndent-ACanvas.TextWidth('9')+1;
|
|
etaCenter: valueBR:=aTLStart+ValueIndent-ACanvas.TextWidth('9') div 2 +1;
|
|
end;
|
|
end else
|
|
valueBR:=ATickStart.X+ValueIndent;
|
|
eopBottom:
|
|
if ATicks then
|
|
case ValueDisplay of
|
|
evdNormal, evdTopLeft, evdBottomRight: valueBR:=aTLStart+ValueIndent;
|
|
otherwise
|
|
if TickAlign=etaInner
|
|
then valueBR:=aTLStart+ValueIndent-ACanvas.TextHeight('1,9')+3
|
|
else valueBR:=aTLStart+ValueIndent;
|
|
end else
|
|
valueBR:=ATickStart.Y+ValueIndent;
|
|
eopLeft:
|
|
if ATicks then
|
|
case ValueDisplay of
|
|
evdNormal, evdTopLeft, evdBottomRight: valueTL:=aTLStart-ValueIndent;
|
|
evdTopLeftInside, evdBttmRightInside:
|
|
case TickAlign of
|
|
etaOuter: valueTL:=aTLStart-ValueIndent;
|
|
etaInner: valueTL:=aTLStart-ValueIndent+ACanvas.TextWidth('9');
|
|
etaCenter: valueTL:=aTLStart-ValueIndent+ACanvas.TextWidth('9') div 2;
|
|
end;
|
|
otherwise
|
|
case TickAlign of
|
|
etaOuter: valueTL:=aTLStart-ValueIndent-ACanvas.TextWidth('9');
|
|
etaInner: valueTL:=aTLStart-ValueIndent;
|
|
etaCenter: valueTL:=aTLStart-ValueIndent-ACanvas.TextWidth('9') div 2;
|
|
end;
|
|
end else
|
|
valueTL:=ATickStart.X-ValueIndent;
|
|
end;
|
|
with ACanvas do
|
|
begin
|
|
Font.Orientation:=FontOrientation;
|
|
aFontColor:=GetColorResolvingDefault(Font.Color, clBtnText);
|
|
if TickDesign>=etd3DLowered then
|
|
Font.Color:=GetMergedColor(aFontColor, Pixels[Width div 2, height div 2], 0.75);
|
|
Brush.Style:=bsClear;
|
|
cosPi1800:=abs(cos(pi_1800*FFontOrientation));
|
|
sinPi1800:=abs(sin(pi_1800*FFontOrientation));
|
|
if aValueVisible>evvBounds then
|
|
begin
|
|
lHelp:=(MaxL-MinL)/high(ValueArray);
|
|
for i:=0 to high(ValueArray) do
|
|
begin
|
|
strVal:=GetStringValue(i);
|
|
if not Reversed
|
|
then lV:=MinL+round(i*lHelp)
|
|
else lV:=MaxL-round(i*lHelp);
|
|
lV:=AStart+lV+GetValuePos;
|
|
DrawValue;
|
|
end;
|
|
end;
|
|
if aValueVisible in [evvBounds, evvAll] then
|
|
begin
|
|
if (aValueVisible=evvBounds) or (ValueArray=nil) or (Min<>ValueArray[0]) then
|
|
begin
|
|
strVal:=GetStringMin;
|
|
lV:=AStart+GetValuePos;
|
|
if Reversed then lV:=lV+LengthPx;
|
|
DrawValue;
|
|
end;
|
|
if (aValueVisible=evvBounds) or (ValueArray=nil) or (Max<>ValueArray[high(ValueArray)]) then
|
|
begin
|
|
strVal:=GetStringMax;
|
|
lV:=AStart+GetValuePos;
|
|
if not Reversed then lV:=lV+LengthPx;
|
|
DrawValue;
|
|
end;
|
|
for i:=0 to high(AExtraValues) do
|
|
if (aValueVisible=evvBounds) and (AExtraValues[i]>Min) and (AExtraValues[i]<Max) then
|
|
begin
|
|
strVal:=GetStringValue(AExtraValues[i], FDigits);
|
|
lV:=round((AExtraValues[i]-Min)*LengthPx/(Max-Min));
|
|
if not Reversed
|
|
then lV:=AStart+lV+GetValuePos
|
|
else lV:=AStart+LengthPx-lV+GetValuePos;
|
|
DrawValue;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
{$IFDEF DBGSCALE} td:=Now; {$ENDIF}
|
|
case AScalePos of
|
|
eopTop:
|
|
begin
|
|
CalcTickPoints(ATickStart.Y, -1);
|
|
AStart:=ATickStart.X;
|
|
end;
|
|
eopRight:
|
|
begin
|
|
CalcTickPoints(ATickStart.X, 1);
|
|
AStart:=ATickStart.Y;
|
|
end;
|
|
eopBottom:
|
|
begin
|
|
CalcTickPoints(ATickStart.Y, 1);
|
|
AStart:=ATickStart.X;
|
|
end;
|
|
eopLeft:
|
|
begin
|
|
CalcTickPoints(ATickStart.X, -1);
|
|
AStart:=ATickStart.Y;
|
|
end;
|
|
end;
|
|
ATicks:=ATicks and (TickVisible>etvNone);
|
|
if ATicks then
|
|
begin
|
|
if TickDesign>=etd3DLowered then
|
|
begin
|
|
AColor3DDark:=GetColorResolvingDefault(AColor3DDark, clBtnShadow);
|
|
AColor3DLight:=GetColorResolvingDefault(AColor3DLight, clBtnHilight);
|
|
end;
|
|
DrawTicks;
|
|
end;
|
|
if AValues and (ValueVisible>evvNone) then DrawValues;
|
|
{$IFDEF DBGSCALE} DebugLn('Scale.Draw '+floattostr((now-td)*24*60*60*1000)); {$ENDIF}
|
|
end;
|
|
|
|
procedure TCustomECScale.EndUpdate;
|
|
begin
|
|
dec(UpdateCount);
|
|
if UpdateCount=0 then RecalcRedraw;
|
|
end;
|
|
|
|
function TCustomECScale.GetPreferredSize(ACanvas: TCanvas; AHorizontal: Boolean;
|
|
ATicks: Boolean = True; AValues: Boolean = True): Integer;
|
|
var bValues: Boolean;
|
|
begin
|
|
Result:=0;
|
|
if ATicks or AValues then
|
|
begin
|
|
if ATicks and (TickVisible>etvNone) then inc(Result,TickIndent+TickLength);
|
|
bValues:= (AValues and (ValueVisible>evvNone));
|
|
if AHorizontal then
|
|
begin { Horizontal }
|
|
if bValues then inc(Result, GetPreferredValuesHeight(ACanvas))
|
|
end else
|
|
begin { Vertical }
|
|
if bValues then inc(Result, GetPreferredValuesWidth(ACanvas))
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TCustomECScale.GetPreferredValuesHeight(ACanvas: TCanvas): Integer;
|
|
begin
|
|
Result:=ValueIndent;
|
|
if ValueDisplay<=evdBottomRight
|
|
then inc(Result, Math.max(GetTextSize(ACanvas, GetStringMax, True),
|
|
GetTextSize(ACanvas, GetStringMin, True)))
|
|
else if TickAlign<>etaInner then inc(Result, ACanvas.TextHeight(',9')-2);
|
|
end;
|
|
|
|
function TCustomECScale.GetPreferredValuesWidth(ACanvas: TCanvas): Integer;
|
|
var aWidth: Integer;
|
|
begin
|
|
Result:=ValueIndent+2;
|
|
if ValueDisplay<=evdBttmRightInside
|
|
then aWidth:=(Math.max(GetTextSize(ACanvas, GetStringMin, False),
|
|
GetTextSize(ACanvas, GetStringMax, False))-2); { -2 is correction }
|
|
case ValueDisplay of
|
|
evdNormal, evdTopLeft, evdBottomRight: inc(Result, aWidth);
|
|
evdTopLeftInside, evdBttmRightInside:
|
|
begin
|
|
inc(Result, aWidth);
|
|
case TickAlign of
|
|
etaInner: dec(Result, ACanvas.TextWidth('9'));
|
|
etaCenter: dec(Result, ACanvas.TextWidth('9') div 2);
|
|
end;
|
|
end;
|
|
evdCompactTopLeft, evdCompactBttmRight:
|
|
begin
|
|
case TickAlign of
|
|
etaOuter: inc(Result, ACanvas.TextWidth('9'));
|
|
etaCenter: inc(Result, ACanvas.TextWidth('9') div 2);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TCustomECScale.GetStringMax: string;
|
|
begin
|
|
Result:='';
|
|
if ValueFormat<>esvfText
|
|
then Result:=GetStringValue(Max, Digits)
|
|
else if FText.Count>0 then Result:=FText[FText.Count-1];
|
|
end;
|
|
|
|
function TCustomECScale.GetStringMin: string;
|
|
begin
|
|
Result:='';
|
|
if ValueFormat<>esvfText
|
|
then Result:=GetStringValue(Min, Digits)
|
|
else if FText.Count>0 then Result:=FText[0];
|
|
end;
|
|
|
|
function TCustomECScale.GetStringPosition(APosition: Double): string;
|
|
begin
|
|
Result:=GetStringPosition(APosition, Digits);
|
|
end;
|
|
|
|
function TCustomECScale.GetStringPosition(APosition: Double; ARound: SmallInt): string;
|
|
var i: Integer;
|
|
begin
|
|
if ValueFormat<>esvfText then
|
|
begin
|
|
if ScaleType=estLogarithmic
|
|
then APosition:=LinearToLogarithmic(APosition, Min, Max, LogarithmBase);
|
|
Result:=GetStringValue(APosition, ARound);
|
|
end else
|
|
begin
|
|
i:=round((APosition-Min)/TickLongValue);
|
|
if (i>=0) and (i<Text.Count)
|
|
then Result:=FText.Strings[i]
|
|
else Result:='';
|
|
end;
|
|
end;
|
|
|
|
function TCustomECScale.GetStringValue(AValue: Double; ARound: Integer): string;
|
|
begin
|
|
if assigned(FOnPrepareValue) then FOnPrepareValue(self, AValue);
|
|
case ValueFormat of
|
|
esvfAutoRound: if ARound<0
|
|
then Result:=floattostr(AValue)
|
|
else Result:=floattostrF(AValue, ffFixed, 1, ARound);
|
|
esvfFixedRound: Result:=floattostrF(AValue, ffFixed, 1, ARound);
|
|
esvfSmartRound:
|
|
begin
|
|
if abs(AValue)>=10 then dec(ARound, trunc(log10(abs(AValue))));
|
|
if (ARound<0) or (frac(AValue)=0) then ARound:=0;
|
|
Result:=floattostrF(AValue, ffFixed, 1, ARound);
|
|
end;
|
|
esvfExponential: Result:=floattostrF(AValue, ffExponent, ARound, ARound);
|
|
esvfHexadecimal: Result:=hexStr(round(AValue), ARound);
|
|
esvfMarkHexadec: Result:='$'+hexStr(round(AValue), ARound);
|
|
esvfOctal: Result:=octStr(round(AValue), ARound);
|
|
esvfBinary: Result:=binStr(round(AValue), ARound);
|
|
esvfDate: Result:=datetostr(AValue, DTFormat);
|
|
esvfTime: Result:=timetostr(AValue, DTFormat);
|
|
end;
|
|
end;
|
|
|
|
function TCustomECScale.GetStringValue(AIndex: Integer): string;
|
|
begin
|
|
Result:='';
|
|
if ValueFormat<>esvfText
|
|
then Result:=GetStringValue(ValueArray[AIndex], Digits)
|
|
else if (AIndex>=0) and (AIndex<FText.Count) then Result:=FText.Strings[AIndex];
|
|
end;
|
|
|
|
function TCustomECScale.GetTextSize(ACanvas: TCanvas; AStrVal: string; AHorizontal: Boolean): Integer;
|
|
var cosPi1800, sinPi1800, aHelp: Double;
|
|
begin
|
|
aHelp:=pi_1800*FontOrientation;
|
|
cosPi1800:=abs(cos(aHelp));
|
|
sinPi1800:=abs(sin(aHelp));
|
|
with ACanvas do
|
|
begin
|
|
if AHorizontal
|
|
then Result:=round(sinPi1800*TextWidth(AStrVal)+cosPi1800*(TextHeight(AStrVal)-2))
|
|
else Result:=round(cosPi1800*TextWidth(AStrVal)+sinPi1800*TextHeight(AStrVal));
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomECScale.Redraw;
|
|
begin
|
|
if (UpdateCount=0) and assigned(OnRedraw) then OnRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.RecalcRedraw;
|
|
begin
|
|
if (UpdateCount=0) and assigned(OnRecalcRedraw) then OnRecalcRedraw;
|
|
end;
|
|
|
|
{ TCustomECScale.Setters }
|
|
|
|
procedure TCustomECScale.SetCorrection(AValue: Double);
|
|
begin
|
|
if FCorrection = AValue then exit;
|
|
FCorrection := AValue;
|
|
if ((TickVisible>etvNone) or (ValueVisible>evvNone)) and (ScaleType=estLinear) then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetDateTimeFormat(const AValue: string);
|
|
begin
|
|
if FDateTimeFormat=AValue then exit;
|
|
FDateTimeFormat:=AValue;
|
|
DTFormat.LongDateFormat:=AValue;
|
|
DTFormat.LongTimeFormat:=AValue;
|
|
if (ValueVisible>evvNone) and (ValueFormat in [esvfDate, esvfTime]) then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetDigits(const AValue: SmallInt);
|
|
begin
|
|
if FDigits=AValue then exit;
|
|
FDigits:=AValue;
|
|
if ValueVisible>evvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetFontOrientation(const AValue: Integer);
|
|
begin
|
|
if FFontOrientation=AValue then exit;
|
|
{FFontOrientation:=AValue;} //seems Qt/GTK2/Win32 works differently now
|
|
if ValueVisible>evvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetLogarithmBase(const AValue: Double);
|
|
begin
|
|
if FLogarithmBase=AValue then exit;
|
|
FLogarithmBase:=AValue;
|
|
if ((TickVisible>etvNone) or (ValueVisible>evvNone))
|
|
and (ScaleType=estLogarithmic) then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetMax(const AValue: Double);
|
|
begin
|
|
if FMax=AValue then exit;
|
|
if (Min<AValue) or (csLoading in Parent.ComponentState) then
|
|
begin
|
|
FMax:=AValue;
|
|
RecalcRedraw;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetMin(const AValue: Double);
|
|
begin
|
|
if FMin=AValue then exit;
|
|
if (AValue<Max) or (csLoading in Parent.ComponentState) then
|
|
begin
|
|
FMin:=AValue;
|
|
RecalcRedraw;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetScaleType(const AValue: TScaleType);
|
|
begin
|
|
if FScaleType=AValue then exit;
|
|
FScaleType:=AValue;
|
|
if (TickVisible>etvNone) or (ValueVisible>evvNone) then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetText(const AValue: TStrings);
|
|
begin
|
|
if FText=AValue then exit;
|
|
FText.Assign(AValue);
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickAlign(const AValue: TTickAlign);
|
|
begin
|
|
if FTickAlign=AValue then exit;
|
|
FTickAlign:=AValue;
|
|
if TickVisible>etvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickColor(const AValue: TColor);
|
|
begin
|
|
if FTickColor=AValue then exit;
|
|
FTickColor:=AValue;
|
|
if TickVisible>etvNone then Redraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickDesign(const AValue: TTickDesign);
|
|
begin
|
|
if FTickDesign=AValue then exit;
|
|
FTickDesign:=AValue;
|
|
if TickVisible>etvNone then Redraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickIndent(const AValue: SmallInt);
|
|
begin
|
|
if FTickIndent=AValue then exit;
|
|
FTickIndent:=AValue;
|
|
RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickLength(const AValue: SmallInt);
|
|
begin
|
|
if FTickLength=AValue then exit;
|
|
FTickLength:=AValue;
|
|
if TickVisible>etvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickLongValue(const AValue: Double);
|
|
begin
|
|
if FTickLongValue=AValue then exit;
|
|
FTickLongValue:=AValue;
|
|
if TickVisible>etvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickMiddleValue(const AValue: Double);
|
|
begin
|
|
if FTickMiddleValue=AValue then exit;
|
|
FTickMiddleValue:=AValue;
|
|
if TickVisible=etvAll then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickShortValue(const AValue: Double);
|
|
begin
|
|
if FTickShortValue=AValue then exit;
|
|
FTickShortValue:=AValue;
|
|
if TickVisible>=etvLongShort then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetTickVisible(const AValue: TTicksVisible);
|
|
begin
|
|
if FTickVisible=AValue then exit;
|
|
FTickVisible:=AValue;
|
|
RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetValueDisplay(const AValue: TValueDisplay);
|
|
begin
|
|
if FValueDisplay=AValue then exit;
|
|
FValueDisplay:=AValue;
|
|
if ValueVisible>evvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetValueFormat(const AValue: TScaleValueFormat);
|
|
begin
|
|
if FValueFormat=AValue then exit;
|
|
FValueFormat:=AValue;
|
|
if ValueVisible>evvNone
|
|
then RecalcRedraw
|
|
else Redraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetValueIndent(const AValue: SmallInt);
|
|
begin
|
|
if FValueIndent=AValue then exit;
|
|
FValueIndent:=AValue;
|
|
if ValueVisible>evvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetValueShift(const AValue: SmallInt);
|
|
begin
|
|
if FValueShift=AValue then exit;
|
|
FValueShift:=AValue;
|
|
if ValueVisible>evvNone then RecalcRedraw;
|
|
end;
|
|
|
|
procedure TCustomECScale.SetValueVisible(const AValue: TValuesVisibility);
|
|
begin
|
|
if FValueVisible=AValue then exit;
|
|
FValueVisible:=AValue;
|
|
RecalcRedraw;
|
|
end;
|
|
|
|
end.
|
|
|
|
|