home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 October / CMCD1004.ISO / Software / Freeware / Programare / th2DGraph / Source / Qth2DGraph.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2004-09-06  |  74.6 KB  |  2,030 lines

  1. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  2. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  3. {MWMWMWMWMWMWMWMWMWMW                                      MWMWMWMWMWMWMWMWMWMW}
  4. {MWMWMWMWMWMWMWMWM       author: tomas.hanak@centrum.cz       WMWMWMWMWMWMWMWMW}
  5. {MWMWMWMWMWMWMWMWMWMW                                      MWMWMWMWMWMWMWMWMWMW}
  6. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  7. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  8.  
  9. unit Qth2DGraph;
  10.  
  11. interface
  12.  
  13. uses
  14.   SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs, QStdCtrls,
  15.   QExtCtrls, QMenus, QTypes, Qt,
  16.   Math;
  17.  
  18. const
  19.   MAX_CURVES = 16;
  20.  
  21. type
  22.   TPlotMode    = (pmDot, pmLine, pmBar);
  23.   TScaleMode   = (smNone, smNumber, smTime);
  24.   TTimeFormat  = (tfHour, tfHourMin, tfHourMinSec, tfMin, tfMinSec, tfSec);
  25.   TDirection   = (diLeftRight, diTopBottom);
  26.  
  27.   TRGBTriple = record
  28.                  RGBtRed  : Byte;
  29.                  RGBtGreen: Byte;
  30.                  RGBtBlue : Byte;
  31.                  RGBtAny  : Byte;
  32.                end;
  33.   TRGBArray  =  array[0..32767] of TRGBTriple;
  34.   PRGBArray  =  ^TRGBArray;
  35.  
  36.   Txyc = record
  37.            X: Extended;
  38.            Y: Extended;
  39.            C: TColor;
  40.          end;
  41.  
  42.   TLayerOpt = record
  43.                 PlotMode: TPlotMode;
  44.                 PenWidth: Integer;
  45.               end;
  46.  
  47.   TGradient = class(TGraphicsObject)
  48.     private
  49.       FColorStart: TColor;
  50.       FColorStop : TColor;
  51.       FDirection : TDirection;
  52.       FEnable    : Boolean;
  53.       procedure SetColorStart(const Value: TColor);
  54.       procedure SetColorStop (const Value: TColor);
  55.       procedure SetDirection (const Value: TDirection);
  56.       procedure SetEnable    (const Value: Boolean);
  57.     protected
  58.       procedure Draw(ACanvas: TCanvas; Rect: TRect); overload;
  59.       procedure Draw(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer); overload;
  60.       property  OnChange;
  61.     public
  62.       constructor Create;
  63.       destructor  Destroy; override;
  64.       procedure   Assign(Source: TPersistent); override;
  65.     published
  66.       property ColorStart: TColor    read FColorStart write SetColorStart  default clGray;
  67.       property ColorStop: TColor     read FColorStop  write SetColorStop   default clSilver;
  68.       property DireCtion: TDirection read FDirection  write SetDirection   default diTopBottom;
  69.       property Enable: Boolean       read FEnable     write SetEnable      default True;
  70.   end;
  71.  
  72.   TLimit = class(TGraphicsObject)
  73.     private
  74.       FAlarmColor: TColor;
  75.       FPen       : TPen;
  76.       FValue     : Extended;
  77.       FVisible   : Boolean;
  78.       procedure SetAlarmColor(const Value: TColor);
  79.       procedure SetPen       (const Value: TPen);
  80.       procedure SetValue     (const Value: Extended);
  81.       procedure SetVisible   (const Value: Boolean);
  82.     protected
  83.       property OnChange;
  84.     public
  85.       constructor Create;
  86.       destructor  Destroy; override;
  87.       procedure   Assign(Source: TPersistent); override;
  88.     published
  89.       property AlarmColor: TColor read FAlarmColor write SetAlarmColor  default clRed;
  90.       property Pen: TPen          read FPen        write SetPen;
  91.       property Value: Extended    read FValue      write SetValue;
  92.       property Visible: Boolean   read FVisible    write SetVisible     default False;
  93.   end;
  94.  
  95.   TAxis = class(TGraphicsObject)
  96.     private
  97.       FArrow         : Boolean;
  98.       FArrowLength   : Integer;
  99.       FArrowWidth    : Integer;
  100.       FDivisions     : Integer;
  101.       FHighLimit     : TLimit;
  102.       FLength        : Integer;
  103.       FLowLimit      : TLimit;
  104.       FMarginBottom  : Integer;
  105.       FMarginLeft    : Integer;
  106.       FMarginTop     : Integer;
  107.       FMarginRight   : Integer;
  108.       FMarks         : Boolean;
  109.       FMarksFont     : TFont;
  110.       FMax           : Extended;
  111.       FMaxNameHeight : Integer;
  112.       FMaxNameWidth  : Integer;
  113.       FMaxValueHeight: Integer;
  114.       FMaxValueWidth : Integer;
  115.       FMin           : Extended;
  116.       FName          : String;
  117.       FNameTmp       : String;
  118.       FNameFont      : TFont;
  119.       FOrientation   : TOrientation;
  120.       FPen           : TPen;
  121.       FScaleMode     : TScaleMode;
  122.       FShowName      : Boolean;
  123.       FTimeFormat    : TTimeFormat;
  124.       FVisible       : Boolean;
  125.       function  FormatTime    (const Format: TTimeFormat; const Value: Extended): String;
  126.       procedure SetArrow      (const Value: Boolean);
  127.       procedure SetArrowLength(const Value: Integer);
  128.       procedure SetArrowWidth (const Value: Integer);
  129.       procedure SetDivisions  (const Value: Integer);
  130.       procedure SetHighLimit  (const Value: TLimit);
  131.       procedure SetLength     (const Value: Integer);
  132.       procedure SetLowLimit   (const Value: TLimit);
  133.       procedure SetMargins;
  134.       procedure SetMarks      (const Value: Boolean);
  135.       procedure SetMarksFont  (const Value: TFont);
  136.       procedure SetMax        (const Value: Extended);
  137.       procedure SetMin        (const Value: Extended);
  138.       procedure SetName       (const Value: String);
  139.       procedure SetNameFont   (const Value: TFont);
  140.       procedure SetOrientation(const Value: TOrientation);
  141.       procedure SetScaleMode  (const Value: TScaleMode);
  142.       procedure SetShowName   (const Value: Boolean);
  143.       procedure SetTimeFormat (const Value: TTimeFormat);
  144.       procedure SetPen        (const Value: TPen);
  145.       procedure SetVisible    (const Value: Boolean);
  146.     protected
  147.       procedure Draw(ACanvas: TCanvas; XStart, YStart: Integer);
  148.       property  OnChange;
  149.     public
  150.       constructor Create;
  151.       destructor  Destroy; override;
  152.       procedure   Assign(Source: TPersistent); override;
  153.       property MarginBottom: Integer     read FMarginBottom;
  154.       property MarginLeft: Integer       read FMarginLeft;
  155.       property MarginRight: Integer      read FMarginRight;
  156.       property MarginTop: Integer        read FMarginTop;
  157.     published
  158.       property Arrow: Boolean            read FArrow       write SetArrow       default True;
  159.       property ArrowLength: Integer      read FArrowLength write SetArrowLength default 15;
  160.       Property ArrowWidth: Integer       read FArrowWidth  write SetArrowWidth  default 7;
  161.       property Divisions: Integer        read FDivisions   write SetDivisions   default 10;
  162.       property HighLimit: TLimit         read FHighLimit   write SetHighLimit;
  163.       property Length: Integer           read FLength      write SetLength      default 100;
  164.       property LowLimit: TLimit          read FLowLimit    write SetLowLimit;
  165.       property Marks: Boolean            read FMarks       write SetMarks       default True;
  166.       property MarksFont: TFont          read FMarksFont   write SetMarksFont;
  167.       property Max: Extended             read FMax         write SetMax;
  168.       property Min: Extended             read FMin         write SetMin;
  169.       property Name: String              read FNameTmp     write SetName;
  170.       property NameFont: TFont           read FNameFont    write SetNameFont;
  171.       property Orientation: TOrientation read FOrientation write SetOrientation default orHorizontal;
  172.       property Pen: TPen                 read FPen         write SetPen;
  173.       property ScaleMode: TScaleMode     read FScaleMode   write SetScaleMode   default smNumber;
  174.       property ShowName: Boolean         read FShowName    write SetShowName    default True;
  175.       property TimeFormat: TTimeFormat   read FTimeFormat  write SetTimeFormat  default tfMinSec;
  176.       property Visible: Boolean          read FVisible     write SetVisible     default True;
  177.   end;
  178.  
  179.   Tth2DGraph = class(TCustomPanel)
  180.     private
  181.       FPlotAreaColor   : TColor;
  182.       FBorder          : TBitmap;
  183.       FBorderGradient  : TGradient;
  184.       FClr             : Boolean;
  185.       FCursorTmp       : TCursor;
  186.       FCursorOldX      : Integer;
  187.       FCursorOldY      : Integer;
  188.       FCursorShow      : Boolean;
  189.       FCursorShowValues: Boolean;
  190.       FCurValFont      : TFont;
  191.       FCurValPosLeft   : Integer;
  192.       FCurValPosTop    : Integer;
  193.       FDataArray       : array[1..MAX_CURVES] of array of Txyc;
  194.       FDataLength      : array[1..MAX_CURVES] of Integer;
  195.       FFreeze          : Boolean;
  196.       FGridShow        : Boolean;
  197.       FGridPen         : TPen;
  198.       FLayerOpt        : array[1..MAX_CURVES] of TLayerOpt;
  199.       FLayerOptions    : Boolean;
  200.       FMargin          : Integer;
  201.       FMarginBottom    : Integer;
  202.       FMarginLeft      : Integer;
  203.       FMarginTop       : Integer;
  204.       FMarginRight     : Integer;
  205.       FPlot            : TBitmap;
  206.       FPlotAreaGradient: TGradient;
  207.       FPlotMode        : TPlotMode;
  208.       FPlotPen         : TPen;
  209.       FRBorder         : TRect;
  210.       FRPlot           : TRect;
  211.       FTitle           : String;
  212.       FTitleFont       : TFont;
  213.       FXAxis           : TAxis;
  214.       FYAxis           : TAxis;
  215.       LastXDrawn       : array[1..MAX_CURVES] of Extended;
  216.       LastYDrawn       : array[1..MAX_CURVES] of Extended;
  217.       Xqnt             : Extended;
  218.       Yqnt             : Extended;
  219.       procedure AdjustR2Dimension;
  220.       procedure ChangedLimits(Sender: TObject);
  221.       procedure DoPaint            (Sender: TObject);
  222.       procedure PlotData           (X, Y: Extended; Color: TColor; Layer: Integer);
  223.       procedure Redraw;
  224.       procedure SetPlotAreaColor   (const Value: TColor);
  225.       procedure SetBorderGradient  (const Value: TGradient);
  226.       procedure SetCursorShow      (const Value: Boolean);
  227.       procedure SetCursorShowValues(const Value: Boolean);
  228.       procedure SetCurValFont      (const Value: TFont);
  229.       procedure SetCurValPosLeft   (const Value: Integer);
  230.       procedure SetCurValPosTop    (const Value: Integer);
  231.       procedure SetFXAxis          (const Value: TAxis);
  232.       procedure SetFYAxis          (const Value: TAxis);
  233.       procedure SetGridShow        (const Value: Boolean);
  234.       procedure SetGridPen         (const Value: TPen);
  235.       procedure SetLayerOptions    (const Value: Boolean);
  236.       procedure SetMargin          (const Value: Integer);
  237.       procedure SetPlotAreaGradient(const Value: TGradient);
  238.       procedure SetPlotMode        (const Value: TPlotMode);
  239.       procedure SetPlotPen         (const Value: TPen);
  240.       procedure SetTitle           (const Value: String);
  241.       procedure SetTitleFont       (const Value: TFont);
  242.     protected
  243.       procedure MouseMove     (Shift: TShiftState; X, Y: Integer); override;
  244.     public
  245.       constructor Create      (AOwner: Tcomponent); override;
  246.       destructor  Destroy;     override;
  247.       procedure   AddXY       (X, Y: Extended; Color: TColor; Layer: Integer = 1); overload;
  248.       procedure   AddXY       (X, Y: Extended); overload;
  249.       procedure   AutoScale   (Layer: Integer = 1);
  250.       procedure   Clear;
  251.       function    ConvertS2W  (X, Y: Integer; var WX, WY: Extended): Boolean;
  252. ////      procedure   AntiAlias;
  253.       procedure   Freeze      (Value: Boolean);
  254.       procedure   HideLayer   (Layer: Integer);
  255.       procedure   LayerOptions(Layer: Integer; PlotMode: TPlotMode; PenWidth: Integer);
  256.       procedure   Paint;       override;
  257.       procedure   UnHideLayer (Layer:Integer);
  258.     published
  259.       property PlotAreaColor: TColor        read FPlotAreaColor    write SetPlotAreaColor    default clBase;
  260.       property BorderGradient: TGradient    read FBorderGradient   write SetBorderGradient;
  261.       property CursorShow: Boolean          read FCursorShow       write SetCursorShow       default True;
  262.       property CursorShowValues: Boolean    read FCursorShowValues write SetCursorShowValues default True;
  263.       property CursorValuesFont: TFont      read FCurValFont       write SetCurValFont;
  264.       property CursorValuesPosLeft: Integer read FCurValPosLeft    write SetCurValPosLeft    default 10;
  265.       property CursorValuesPosTop: Integer  read FCurValPosTop     write SetCurValPosTop     default 5;
  266.       property GridShow: Boolean            read FGridShow         write SetGridShow         default True;
  267.       property GridPen: TPen                read FGridPen          write SetGridPen;
  268.       property LayerOption: Boolean         read FLayerOptions     write SetLayerOptions     default False;
  269.       property Margin: Integer              read FMargin           write SetMargin           default 15;
  270.       property PlotAreaGradient: TGradient  read FPlotAreaGradient write SetPlotAreaGradient;
  271.       property PlotMode: TPlotMode          read FPlotMode         write SetPlotMode;
  272.       property PlotPen: TPen                read FPlotPen          write SetPlotPen;
  273.       property XAxis: TAxis                 read FXAxis            write SetFXAxis;
  274.       property YAxis: TAxis                 read FYAxis            write SetFYAxis;
  275.       property Title: String                read FTitle            write SetTitle;
  276.       property TitleFont: TFont             read FTitleFont        write SetTitleFont;
  277.       property Align                        default alNone;
  278.       property Anchors;
  279.       property BevelInner;
  280.       property BevelOuter;
  281.       property BevelWidth;
  282.       property Bitmap;
  283.       property BorderWidth;
  284.       property BorderStyle;
  285.       property Color                        default clBackground;
  286.       property Constraints;
  287.       property DragMode;
  288.       property Enabled;
  289.       property ParentColor;
  290.       property ParentShowHint;
  291.       property PopupMenu;
  292.       property ShowHint;
  293.       property TabOrder;
  294.       property TabStop                      default False;
  295.       property Visible;
  296.       property OnClick;
  297.       property OnContextPopup;
  298.       property OnDblClick;
  299.       property OnDragDrop;
  300.       property OnDragOver;
  301.       property OnEndDrag;
  302.       property OnEnter;
  303.       property OnExit;
  304.       property OnMouseDown;
  305.       property OnMouseEnter;
  306.       property OnMouseLeave;
  307.       property OnMouseMove;
  308.       property OnMouseUp;
  309.       property OnResize;
  310.       property OnStartDrag;
  311.   end;
  312.  
  313. function  Color2RGB(Color: TColor): Integer;
  314. function  ENDL: String;
  315. procedure Register;
  316.  
  317. implementation
  318.  
  319. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  320.  
  321. function Color2RGB(Color: TColor): Integer;
  322. begin
  323.   if (Color and $FF000000) <> 0 then begin
  324.         Color := ColorToRGB(Color);
  325.         Color := ((Color and $FF0000) shr 16) or
  326.                   (Color and $00FF00)         or
  327.                  ((Color and $0000FF) shl 16);
  328.       end;
  329.   Result := $FFFFFF and Color;
  330. end;
  331. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  332.  
  333. function ENDL: String;
  334. begin
  335.   Result := Char($0A);
  336. {$IFDEF MSWINDOWS}
  337.   Result := Char($0D) + Result;
  338. {$ENDIF}
  339. end;
  340. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  341.  
  342. procedure Register;
  343. begin
  344.   RegisterComponents('thSystem', [Tth2DGraph]);
  345. end;
  346. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  347. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  348.  
  349. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  350. {MWM  TGradient - private metods  WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  351. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  352.  
  353. procedure TGradient.SetColorStart(const Value: TColor);
  354. begin
  355.   if FColorStart = Value then Exit;
  356.   FColorStart := Value;
  357.   Changed;
  358. end;
  359. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  360.  
  361. procedure TGradient.SetColorStop(const Value: TColor);
  362. begin
  363.   if FColorStop = Value then Exit;
  364.   FColorStop := Value;
  365.   Changed;
  366. end;
  367. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  368.  
  369. procedure TGradient.SetDirection(const Value: TDirection);
  370. begin
  371.   if FDirection = Value then Exit;
  372.   FDirection := Value;
  373.   Changed;
  374. end;
  375. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  376.  
  377. procedure TGradient.SetEnable(const Value: Boolean);
  378. begin
  379.   if FEnable = Value then Exit;
  380.   FEnable := Value;
  381.   Changed;
  382. end;
  383.  
  384. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  385. {MWM  TGradient - protected metods  WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  386. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  387.  
  388. procedure TGradient.Draw(ACanvas: TCanvas; Rect: TRect);
  389. begin
  390.   Draw(ACanvas, Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
  391. end;
  392.  
  393. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  394.  
  395. procedure TGradient.Draw(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer);
  396. var R1, G1, B1: Byte;
  397.     R2, G2, B2: Byte;
  398.     R3, G3, B3: Byte;
  399.     n         : Integer;
  400.     R         : TRect; 
  401. begin
  402.   R1 :=  Color2RGB(FColorStart) and $0000FF;
  403.   G1 := (Color2RGB(FColorStart) and $00FF00) shr 8;
  404.   B1 := (Color2RGB(FColorStart) and $FF0000) shr 16;
  405.   R2 :=  Color2RGB(FColorStop)  and $0000FF;
  406.   G2 := (Color2RGB(FColorStop)  and $00FF00) shr 8;
  407.   B2 := (Color2RGB(FColorStop)  and $FF0000) shr 16;
  408.   if FDirection = diLeftRight then begin
  409.         for n := 0 to X2 - X1 - 1 do begin
  410.             R3 := R1 + Round(n * (R2 - R1) / (X2 - X1 - 1));
  411.             G3 := G1 + Round(n * (G2 - G1) / (X2 - X1 - 1));
  412.             B3 := B1 + Round(n * (B2 - B1) / (X2 - X1 - 1));
  413.             ACanvas.Brush.Color := R3 or (G3 shl 8) or (B3 shl 16);
  414.             R.Left   := X1 + n;
  415.             R.Top    := Y1;
  416.             R.Right  := X1 + n+1;
  417.             R.Bottom := Y2;
  418.             ACanvas.FillRect(R);
  419.           end;  
  420.       end
  421.     else begin
  422.         for n := 0 to Y2 - Y1 - 1 do begin
  423.             R3 := R1 + Round(n * (R2 - R1) / (Y2 - Y1 - 1));
  424.             G3 := G1 + Round(n * (G2 - G1) / (Y2 - Y1 - 1));
  425.             B3 := B1 + Round(n * (B2 - B1) / (Y2 - Y1 - 1));
  426.             ACanvas.Brush.Color := R3 or (G3 shl 8) or (B3 shl 16);
  427.             R.Left   := X1;
  428.             R.Top    := Y1 + n;
  429.             R.Right  := X2;
  430.             R.Bottom := Y1 + n+1;
  431.             ACanvas.FillRect(R);
  432.           end;
  433.       end;
  434. end;
  435.  
  436. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  437. {MWM  TGradient - public metod  WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  438. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  439.  
  440. constructor TGradient.Create;
  441. begin
  442.   inherited Create;
  443.   FColorStart := clGray;
  444.   FColorStop  := clSilver;
  445.   FDirection  := diTopBottom;
  446.   FEnable     := True;
  447. end;
  448. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  449.  
  450. destructor TGradient.Destroy;
  451. begin
  452.   inherited Destroy;
  453. end;
  454. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  455.  
  456. procedure TGradient.Assign(Source: TPersistent);
  457. begin
  458.   if Source is TGradient then begin
  459.         DisableChanged;
  460.         try
  461.           Lock;
  462.           try
  463.             TGradient(Source).Lock;
  464.             try
  465.               FColorStart := TGradient(Source).ColorStart;
  466.               FColorStop  := TGradient(Source).ColorStop;
  467.               FDirection  := TGradient(Source).Direction;
  468.               FEnable     := TGradient(Source).Enable;
  469.             finally
  470.               TGradient(Source).Unlock;
  471.             end;
  472.           finally
  473.             Unlock;
  474.           end;
  475.         finally
  476.           EnableChanged;
  477.           Changed;
  478.         end;
  479.       end
  480.     else
  481.       inherited Assign(Source);
  482. end;
  483.  
  484. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  485. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  486.  
  487. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  488. {MWM  TLimit - private metods  MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  489. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  490.  
  491. procedure TLimit.SetAlarmColor(const Value: TColor);
  492. begin
  493.   if FAlarmColor = Value then Exit;
  494.   FAlarmColor := Value;
  495.   Changed;
  496. end;
  497. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  498.  
  499. procedure TLimit.SetPen(const Value: TPen);
  500. begin
  501.   if FPen = Value then Exit;
  502.   FPen.Assign(Value);
  503.   Changed;
  504. end;
  505. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  506.  
  507. procedure TLimit.SetValue(const Value: Extended);
  508. begin
  509.   if FValue = Value then Exit;
  510.   FValue := Value;
  511.   Changed;
  512. end;
  513. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  514.  
  515. procedure TLimit.SetVisible(const Value: Boolean);
  516. begin
  517.   if FVisible = Value then Exit;
  518.   FVisible := Value;
  519.   Changed;
  520. end;
  521.  
  522. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  523. {MWM  TLimit - protected metods  MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  524. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  525.  
  526.  
  527. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  528. {MWM  TLimit - public metod  MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  529. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  530.  
  531. constructor TLimit.Create;
  532. begin
  533.   inherited Create;
  534.   FAlarmColor   := clRed;
  535.   FPen          := TPen.Create;
  536.   FPen.OnChange := OnChange;
  537.   FPen.Color    := clRed;
  538.   FPen.Style    := psDash;
  539.   FPen.Width    := 2;
  540.   FValue        := 0;
  541.   FVisible      := False;
  542. end;
  543. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  544.  
  545. destructor TLimit.Destroy;
  546. begin
  547.   if Assigned(FPen) then FreeAndNil(FPen);
  548.   inherited Destroy;
  549. end;
  550. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  551.  
  552. procedure TLimit.Assign(Source: TPersistent);
  553. begin
  554.   if Source is TLimit then begin
  555.         DisableChanged;
  556.         try
  557.           Lock;
  558.           try
  559.             TLimit(Source).Lock;
  560.             try
  561.               FAlarmColor := TLimit(Source).AlarmColor;
  562.               FPen.Assign   (TLimit(Source).Pen);
  563.               FValue      := TLimit(Source).Value;
  564.               FVisible    := TLimit(Source).Visible;
  565.             finally
  566.               TLimit(Source).Unlock;
  567.             end;
  568.           finally
  569.             Unlock;
  570.           end;
  571.         finally
  572.           EnableChanged;
  573.           Changed;
  574.         end;
  575.       end
  576.     else
  577.       inherited Assign(Source);
  578. end;
  579.  
  580. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  581. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  582.  
  583. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  584. {MWM  TAxis - private metods  WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  585. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  586.  
  587. function TAxis.FormatTime(const Format: TTimeFormat; const Value: Extended): String;
  588. var Time, H, M, S: Int64;
  589. begin
  590.   if Value < 0 then Result := '-'
  591.                else Result := '';
  592.   Time := Trunc(Abs(Value));
  593.   H := Time div 3600;
  594.   if Format in [tfHourMin, tfHourMinSec] then
  595.       M := (Time mod 3600) div 60
  596.     else
  597.       M := Time div 60;
  598.   if Format in [tfHourMinSec, tfMinSec] then
  599.       S := (Time mod 3600) mod 60
  600.     else
  601.       S := Time;
  602.  
  603.   if Format in [tfHour, tfHourMin, tfHourMinSec] then
  604.       Result := Result + IntToStr(H);
  605.   if Format in [tfHourMin, tfHourMinSec] then begin
  606.         Result := Result + ':';
  607.         if M < 10 then Result := Result + '0';
  608.       end;
  609.   if Format in [tfHourMin, tfHourMinSec, tfMin, tfMinSec] then
  610.       Result := Result + IntToStr(M);
  611.   if Format in [tfHourMinSec, tfMinSec] then begin
  612.         Result := Result + ':';
  613.         if S < 10 then Result := Result + '0';
  614.       end;
  615.   if Format in [tfHourMinSec, tfMinSec, tfSec] then
  616.       Result := Result + IntToStr(S);
  617. end;
  618. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  619.  
  620. procedure TAxis.SetArrow(const Value: Boolean);
  621. begin
  622.   if FArrow = Value then Exit;
  623.   FArrow := Value;
  624.   SetMargins;
  625.   Changed;
  626. end;
  627. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  628.  
  629. procedure TAxis.SetArrowLength(const Value: Integer);
  630. begin
  631.   if FArrowLength = Value then Exit;
  632.   FArrowLength := Value;
  633.   SetMargins;
  634.   Changed;
  635. end;
  636. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  637.  
  638. procedure TAxis.SetArrowWidth(const Value: Integer);
  639. begin
  640.   if FArrowWidth = Value then Exit;
  641.   FArrowWidth := Value;
  642.   SetMargins;
  643.   Changed;
  644. end;
  645. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  646.  
  647. procedure TAxis.SetDivisions(const Value: Integer);
  648. begin
  649.   if FDivisions = Value then Exit;
  650.   if FDivisions < 1 then FDivisions := 1
  651.                     else FDivisions := Value;
  652.   Changed;
  653. end;
  654. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  655.  
  656. procedure TAxis.SetHighLimit(const Value: TLimit);
  657. begin
  658.   if FHighLimit = Value then Exit;
  659.   FHighLimit.Assign(Value);
  660.   if FHighLimit.Value < FLowLimit.Value then FHighLimit.Value := FLowLimit.Value;
  661.   Changed;
  662. end;
  663. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  664.  
  665. procedure TAxis.SetLength(const Value: Integer);
  666. begin
  667.   if FLength = Value then Exit;
  668.   if FLength < 1 then FLength := 1
  669.                  else FLength := Value;
  670.   Changed;
  671. end;
  672. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  673.  
  674. procedure TAxis.SetLowLimit(const Value: TLimit);
  675. begin
  676.   if FLowLimit = Value then Exit;
  677.   FLowLimit.Assign(Value);
  678.   if FLowLimit.Value > FHighLimit.Value then FLowLimit.Value := FHighLimit.Value;
  679.   Changed;
  680. end;
  681. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  682.  
  683. procedure TAxis.SetMargins;
  684.   function GetMax(V1, V2: Integer): Integer;
  685.   begin
  686.     if V1 > V2 then Result := V1
  687.                else Result := V2;
  688.   end;
  689. var AW2, PW, PW2, PWM2, PWM02: Integer;
  690.     A, B, C, D, n            : Integer;
  691.     Str                      : String;
  692.     X                        : Extended;
  693.     BMP                      : TBitmap; // Only for finding TextHeight and TextWidth
  694. begin
  695.   AW2  := FArrowWidth div 2;
  696.   PW   := FPen.Width;
  697.   PW2  := PW div 2;
  698.   PWM2 := PW mod 2;
  699.   if PW > 1 then PWM02 := PWM2
  700.             else PWM02 := 0;
  701.   FMaxNameHeight  := 0;
  702.   FMaxNameWidth   := 0;
  703.   FMaxValueHeight := 0;
  704.   FMaxValueWidth  := 0;
  705.   BMP := TBitmap.Create;
  706.   try
  707.     BMP.Width  := 1;
  708.     BMP.Height := 1;
  709.     BMP.Canvas.Font.Assign(FNameFont);
  710.     if FShowName then
  711.         if FOrientation = orHorizontal
  712.           then FMaxNameHeight := BMP.Canvas.TextHeight(FName)  // Use not FNameFont.Height!!!
  713.           else FMaxNameWidth  := BMP.Canvas.TextWidth (FName); // isn't equal
  714.     if FScaleMode <> smNone then begin
  715.           BMP.Canvas.Font.Assign(FMarksFont);
  716.           for n := 0 to FDivisions do begin
  717.               X := (n * (FMax - FMin) / FDivisions) + FMin;
  718.               if FScaleMode = smTime then
  719.                   Str := FormatTime(FTimeFormat, X)
  720.                 else
  721.                   if X < 1000
  722.                     then Str := FormatFloat('0.##',      X)
  723.                     else Str := FormatFloat('0.## e-00', X);
  724.               if FOrientation = orHorizontal then begin
  725.                      if BMP.Canvas.TextHeight(Str) > FMaxValueHeight then
  726.                          FMaxValueHeight := BMP.Canvas.TextHeight(Str);
  727.                   end
  728.                 else if BMP.Canvas.TextWidth (Str) > FMaxValueWidth  then
  729.                          FMaxValueWidth  := BMP.Canvas.TextWidth (Str);
  730.             end;
  731.         end;
  732.   finally
  733.     BMP.Free;
  734.   end;
  735.   A := 0;
  736.   if FMarks then
  737.       if FArrow then begin
  738.             B := GetMax(FArrowLength, PW2);
  739.             C := GetMax(AW2 + 1 - PWM02, FMaxValueWidth  + FMaxNameWidth  + PW + PW2);
  740.             D := GetMax(AW2,             FMaxValueHeight + FMaxNameHeight + PW + PW2 - (1 - PWM2));
  741.           end
  742.         else begin
  743.             B := PW2;
  744.             C := FMaxValueWidth  + FMaxNameWidth  + PW + PW2;
  745.             D := FMaxValueHeight + FMaxNameHeight + PW + PW2 - (1 - PWM2);
  746.           end
  747.     else
  748.       if FArrow then begin
  749.             B := FArrowLength;
  750.             C := GetMax(AW2 + 1 - PWM02, FMaxValueWidth  + FMaxNameWidth  + PW2);
  751.             D := GetMax(AW2,             FMaxValueHeight + FMaxNameHeight + PW2 - (1 - PWM2));
  752.           end
  753.         else begin
  754.             B := 0;
  755.             C := FMaxValueWidth  + FMaxNameWidth  + PW2;
  756.             D := FMaxValueHeight + FMaxNameHeight + PW2 - (1 - PWM2);
  757.           end;
  758.   if FOrientation = orHorizontal then begin
  759.         FMarginLeft   := A;
  760.         FMarginRight  := B;
  761.         FMarginTop    := C;
  762.         FMarginBottom := D;
  763.       end
  764.     else begin
  765.         FMarginLeft   := C;
  766.         FMarginRight  := D;
  767.         FMarginTop    := B;
  768.         FMarginBottom := A;
  769.       end;
  770. end;
  771. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  772.  
  773. procedure TAxis.SetMarks(const Value: Boolean);
  774. begin
  775.   if FMarks = Value then Exit;
  776.   FMarks := Value;
  777.   SetMargins;
  778.   Changed;
  779. end;
  780. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  781.  
  782. procedure TAxis.SetMarksFont(const Value: TFont);
  783. begin
  784.   if FMarksFont = Value then Exit;
  785.   FMarksFont.Assign(Value);
  786.   SetMargins;
  787.   Changed;
  788. end;
  789. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  790.  
  791. procedure TAxis.SetMax(const Value: Extended);
  792. begin
  793.   if FMax = Value then Exit;
  794.   FMax := Value;
  795.   SetMargins;
  796.   Changed;
  797. end;
  798. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  799.  
  800. procedure TAxis.SetMin(const Value: Extended);
  801. begin
  802.   if FMin = Value then Exit;
  803.   FMin := Value;
  804.   SetMargins;
  805.   Changed;
  806. end;
  807. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  808.  
  809. procedure TAxis.SetName(const Value: String);
  810. var n: Integer;
  811. begin
  812.   if FNameTmp = Value then Exit;
  813.   FNameTmp := Value;
  814.   FName := FNameTmp;
  815.   if FOrientation = orVertical then
  816.       for n := System.Length(Value) downto 2 do
  817.         Insert(ENDL, FName, n);
  818.   SetMargins;
  819.   Changed;
  820. end;
  821. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  822.  
  823. procedure TAxis.SetNameFont(const Value: TFont);
  824. begin
  825.   if FNameFont = Value then Exit;
  826.   FNameFont.Assign(Value);
  827.   SetMargins;
  828.   Changed;
  829. end;
  830. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  831.  
  832. procedure TAxis.SetOrientation(const Value: TOrientation);
  833. var n: Integer;
  834. begin
  835.   if FOrientation = Value then Exit;
  836.   FOrientation := Value;
  837.   FName := FNameTmp;
  838.   if FOrientation = orVertical then
  839.       for n := System.Length(FNameTmp) downto 2 do
  840.         Insert(ENDL, FName, n);
  841.   SetMargins;
  842.   Changed;
  843. end;
  844. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  845.  
  846. procedure TAxis.SetPen(const Value: TPen);
  847. begin
  848.   FPen.Assign(Value);
  849.   SetMargins;
  850.   Changed;
  851. end;
  852. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  853.  
  854. procedure TAxis.SetScaleMode(const Value: TScaleMode);
  855. begin
  856.   if FScaleMode = Value then Exit;
  857.   FScaleMode := Value;
  858.   SetMargins;
  859.   Changed;
  860. end;
  861. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  862.  
  863. procedure TAxis.SetShowName(const Value: Boolean);
  864. begin
  865.   if FShowName = Value then Exit;
  866.   FShowName := Value;
  867.   SetMargins;
  868.   Changed;
  869. end;
  870. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  871.  
  872. procedure TAxis.SetTimeFormat(const Value: TTimeFormat);
  873. begin
  874.   if FTimeFormat = Value then Exit;
  875.   FTimeFormat := Value;
  876.   SetMargins;
  877.   Changed;
  878. end;
  879. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  880.  
  881. procedure TAxis.SetVisible(const Value: Boolean);
  882. begin
  883.   if FVisible = Value then Exit;
  884.   FVisible := Value;
  885.   SetMargins;
  886.   Changed;
  887. end;
  888.  
  889. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  890. {MWM  TAxis - protected metods  WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  891. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  892.  
  893. procedure TAxis.Draw(ACanvas: TCanvas; XStart, YStart: Integer);
  894. var AW2, PW, PW2, PWM02: Integer;
  895.     tmpX, tmpY, n      : Integer;
  896.     Str                : String;
  897.     X, Y               : Extended;
  898.     tmpPen             : TPen;
  899. begin
  900.   if not Visible then Exit;
  901.   tmpPen := TPen.Create;
  902.   try
  903.     tmpPen.Assign(ACanvas.Pen);
  904.     ACanvas.Pen.Assign(FPen);
  905.     AW2 := FArrowWidth div 2;
  906.     PW  := FPen.Width;
  907.     PW2 := PW div 2;
  908.     if PW > 1 then PWM02 := PW mod 2
  909.               else PWM02 := 0;
  910.     case FOrientation of
  911.       orHorizontal: begin
  912.           ACanvas.MoveTo(XStart,           YStart);
  913.           ACanvas.LineTo(XStart + FLength, YStart);
  914.           if FArrow then begin  // Draw axis arrow
  915.                   ACanvas.MoveTo(FLength + XStart, YStart);
  916.                   ACanvas.LineTo(FLength + XStart + FArrowLength - 2*AW2, YStart);
  917.                   ACanvas.Pen.Width := 1;
  918.                   for n := 0 to AW2 do begin
  919.                       ACanvas.MoveTo(FLength + XStart + FArrowLength - 2*AW2 - 1, YStart - n - (1 - PWM02));
  920.                       ACanvas.LineTo(FLength + XStart + FArrowLength - 2*n,       YStart - n - (1 - PWM02));
  921.                       ACanvas.MoveTo(FLength + XStart + FArrowLength - 2*AW2 - 1, YStart + n);
  922.                       ACanvas.LineTo(FLength + XStart + FArrowLength - 2*n,       YStart + n);
  923.                     end;
  924.                   ACanvas.Pen.Width := PW;
  925.               end;
  926.           if FMarks then  // Draw axis marks
  927.               for n := 0 to FDivisions do begin
  928.                   ACanvas.MoveTo(Round((n * FLength) / FDivisions) + XStart, YStart +  PW + PW2 + PWM02);
  929.                   ACanvas.LineTo(Round((n * FLength) / FDivisions) + XStart, YStart);
  930.                   ACanvas.MoveTo(Round((n * FLength) / FDivisions) + XStart, YStart - (PW + PW2));
  931.                   ACanvas.LineTo(Round((n * FLength) / FDivisions) + XStart, YStart);
  932.                 end;
  933.           if FScaleMode <> smNone then begin  // Write axis values
  934.                 ACanvas.Font.Assign(FMarksFont);
  935.                 for n := 0 to FDivisions do begin
  936.                     X := (n * (FMax - FMin) / FDivisions) + FMin;
  937.                     if FScaleMode = smTime then
  938.                         Str := FormatTime(FTimeFormat, X)
  939.                       else
  940.                         if X < 1000 then Str := FormatFloat('0.##', X)
  941.                                     else Str := FormatFloat('0.## e-00', X);
  942.                     tmpX := Round(n * FLength / FDivisions) + XStart - ACanvas.TextWidth(Str) div 2;
  943.                     tmpY := YStart + PW2;
  944.                     if Marks then Inc(tmpY, PW);
  945.                    ACanvas.TextOut(tmpX, tmpY, Str);
  946.                   end;
  947.               end;
  948.             if FShowName then begin
  949.                   ACanvas.Font.Assign(FNameFont);
  950.                   tmpX := XStart + (FLength - ACanvas.TextWidth(FName)) div 2;
  951.                   tmpY := YStart + (FMarginBottom - ACanvas.TextHeight(FName));
  952.                   ACanvas.TextOut(tmpX, tmpY, FName);
  953.                 end;
  954.         end; //orHorizontal
  955.       orVertical: begin
  956.           ACanvas.MoveTo(XStart, YStart);
  957.           ACanvas.LineTo(XStart, YStart - Length);
  958.           if FArrow then begin  // Draw axis arrow
  959.                   ACanvas.MoveTo(XStart, YStart - FLength);
  960.                   ACanvas.LineTo(XStart, YStart - (FLength + FArrowLength - 2*AW2));
  961.                   ACanvas.Pen.Width := 1;
  962.                   for n := 0 to AW2 do begin
  963.                       ACanvas.MoveTo(XStart - n - (1 - PWM02), YStart - (FLength + FArrowLength - 2*AW2 - 1));
  964.                       ACanvas.LineTo(XStart - n - (1 - PWM02), YStart - (FLength + FArrowLength - 2*n));
  965.                       ACanvas.MoveTo(XStart + n,               YStart - (FLength + FArrowLength - 2*AW2 - 1));
  966.                       ACanvas.LineTo(XStart + n,               YStart - (FLength + FArrowLength - 2*n));
  967.                     end;
  968.                   ACanvas.Pen.Width := PW;
  969.               end;
  970.           if FMarks then  // Draw axis marks
  971.               for n := 0 to FDivisions do begin
  972.                   ACanvas.MoveTo(XStart +  PW + PW2 + PWM02, YStart - Round((n * FLength) / FDivisions));
  973.                   ACanvas.LineTo(XStart,                     YStart - Round((n * FLength) / FDivisions));
  974.                   ACanvas.MoveTo(XStart - (PW + PW2),        YStart - Round((n * FLength) / FDivisions));
  975.                   ACanvas.LineTo(XStart,                     YStart - Round((n * FLength) / FDivisions));
  976.                 end;
  977.           if FScaleMode <> smNone then begin
  978.                 ACanvas.Font.Assign(FMarksFont);
  979.                 for n := 0 to FDivisions do begin
  980.                     Y := (n * (FMax - FMin) / FDivisions) + FMin;
  981.                     if FScaleMode = smTime then
  982.                         Str := FormatTime(FTimeFormat, Y)
  983.                       else
  984.                         if Y < 1000 then
  985.                             Str := FormatFloat('0.##', Y)
  986.                           else
  987.                             Str := FormatFloat('0.##E-00', Y);
  988.                     tmpX := XStart - ACanvas.TextWidth(Str) - PW2 - 1;
  989.                     if Marks then Dec(tmpX, PW);
  990.                     tmpY := YStart - Round((n * FLength) / FDivisions) - ACanvas.TextHeight(Str) div 2;
  991.                    ACanvas.TextOut(tmpX, tmpY, Str);
  992.                   end;
  993.               end;
  994.             if FShowName then begin
  995.                   ACanvas.Font.Assign(FNameFont);
  996.                   tmpX := XStart - FMarginLeft;
  997.                   tmpY := YStart - (FLength + ACanvas.TextHeight(FName)) div 2;
  998.                   ACanvas.TextOut(tmpX, tmpY, FName);
  999.                 end;
  1000.         end; //orVertical
  1001.     end; //case
  1002.  
  1003.   finally
  1004.     ACanvas.Pen.Assign(tmpPen);
  1005.     tmpPen.Free;
  1006.   end;
  1007. end;
  1008.  
  1009. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1010. {MWM  TAxis - public metods  MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1011. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1012.  
  1013. constructor TAxis.Create;
  1014. begin
  1015.   inherited Create;
  1016.   FHighLimit := TLimit.Create;
  1017.   FLowLimit  := TLimit.Create;
  1018.   FMarksFont := TFont.Create;
  1019.   FNameFont  := TFont.Create;
  1020.   FPen       := TPen.Create;
  1021.   FHighLimit.OnChange := OnChange;
  1022.   FLowLimit.OnChange  := OnChange;
  1023.   FMarksFont.OnChange := OnChange;
  1024.   FNameFont.OnChange  := OnChange;
  1025.   FPen.OnChange       := OnChange;
  1026.   FArrow           := True;
  1027.   FArrowLength     := 25;
  1028.   FArrowWidth      := 11;
  1029.   FDivisions       := 10;
  1030.   FHighLimit.Value := 9;
  1031.   FLowLimit.Value  := 1;
  1032.   FLength          := 100;
  1033.   FMarks           := True;
  1034.   FMax             := 10;
  1035.   FMin             := 0;
  1036.   FOrientation     := orHorizontal;
  1037.   FPen.Color       := clNavy;
  1038.   FPen.Width       := 3;
  1039.   FScaleMode       := smNumber;
  1040.   FShowName        := True;
  1041.   FTimeFormat      := tfMinSec;
  1042.   FVisible         := True;
  1043.   Name             := '>axis name<';
  1044.   SetMargins;
  1045. end;
  1046. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1047.  
  1048. destructor TAxis.Destroy;
  1049. begin
  1050.   if Assigned(FPen)       then FreeAndNil(FPen);
  1051.   if Assigned(FNameFont)  then FreeAndNil(FNameFont);
  1052.   if Assigned(FMarksFont) then FreeAndNil(FMarksFont);
  1053.   if Assigned(FLowLimit)  then FreeAndNil(FLowLimit);
  1054.   if Assigned(FHighLimit) then FreeAndNil(FHighLimit);
  1055.   inherited Destroy;
  1056. end;
  1057. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1058.  
  1059. procedure TAxis.Assign(Source: TPersistent);
  1060. begin
  1061.   if Source is TAxis then begin
  1062.         DisableChanged;
  1063.         try
  1064.           Lock;
  1065.           try
  1066.             TAxis(Source).Lock;
  1067.             try
  1068.               FArrow         := TAxis(Source).Arrow;
  1069.               FArrowLength   := TAxis(Source).FArrowLength;
  1070.               FArrowWidth    := TAxis(Source).ArrowWidth;
  1071.               if TAxis(Source).FDivisions < 1 then FDivisions := 1
  1072.                                 else FDivisions := TAxis(Source).Divisions;
  1073.               FHighLimit.Assign(TAxis(Source).HighLimit);
  1074.               if TAxis(Source).FLength < 1 then FLength := 1
  1075.                              else FLength := TAxis(Source).Length;
  1076.               FLowLimit.Assign (TAxis(Source).LowLimit);
  1077.               FMarks         := TAxis(Source).Marks;
  1078.               FMarksFont.Assign(TAxis(Source).MarksFont);
  1079.               FMax           := TAxis(Source).Max;
  1080.               FMin           := TAxis(Source).Min;
  1081.               FNameFont.Assign (TAxis(Source).NameFont);
  1082.               FOrientation   := TAxis(Source).Orientation;
  1083.               FPen.Assign      (TAxis(Source).Pen);
  1084.               FScaleMode     := TAxis(Source).ScaleMode;
  1085.               FShowName      := TAxis(Source).ShowName;
  1086.               FTimeFormat    := TAxis(Source).TimeFormat;
  1087.               FVisible       := TAxis(Source).Visible;
  1088.               Name           := TAxis(Source).Name;
  1089.               SetMargins;
  1090.             finally
  1091.               TAxis(Source).Unlock;
  1092.             end;
  1093.           finally
  1094.             Unlock;
  1095.           end;
  1096.         finally
  1097.           EnableChanged;
  1098.           Changed;
  1099.         end;
  1100.       end
  1101.     else
  1102.       inherited Assign(Source);
  1103. end;
  1104.  
  1105. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1106. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1107.  
  1108. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1109. {MWM  Tth2DGraph - private metods  MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1110. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1111.  
  1112. procedure Tth2DGraph.AdjustR2Dimension;
  1113. begin
  1114.   try
  1115.     Xqnt := FXAxis.Length  / (FXAxis.Max - FXAxis.Min);
  1116.   except
  1117.     on EZeroDivide do Xqnt := FXAxis.Length;
  1118.   end;
  1119.   try
  1120.     Yqnt := FYAxis.Length / (FYAxis.Max - FYAxis.Min);
  1121.   except
  1122.     on EZeroDivide do Yqnt := FYAxis.Length;
  1123.   end;
  1124. end;
  1125. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1126.  
  1127. procedure Tth2DGraph.ChangedLimits(Sender: TObject);
  1128. var tmp: Extended;
  1129. begin
  1130.   if FXAxis.HighLimit.Value < FXAxis.LowLimit.Value then begin
  1131.         tmp              := FXAxis.LowLimit.Value;
  1132.         FXAxis.LowLimit.Value  := FXAxis.HighLimit.Value;
  1133.         FXAxis.HighLimit.Value := tmp;
  1134.       end;
  1135.   if FYAxis.HighLimit.Value < FYAxis.LowLimit.Value then begin
  1136.         tmp              := FYAxis.LowLimit.Value;
  1137.         FYAxis.LowLimit.Value  := FYAxis.HighLimit.Value;
  1138.         FYAxis.HighLimit.Value := tmp;
  1139.       end;
  1140.   Redraw;
  1141. end;
  1142. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1143.  
  1144. procedure Tth2DGraph.DoPaint(Sender:TObject);
  1145. begin
  1146.   Redraw; // Redraw is without parameters
  1147. end;
  1148. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1149.  
  1150. procedure Tth2DGraph.PlotData(X, Y: Extended; Color: TColor; Layer: Integer);
  1151. var L, B      : Integer;
  1152.     S, S2     : Integer;
  1153.     Xold, Yold: Extended;
  1154.     Xnew, Ynew: Extended;
  1155.     Xpix, Ypix: Int64;
  1156.     Xll, Xhl  : Extended;
  1157.     Yll, Yhl  : Extended;
  1158. {MWMWMWMW}
  1159.   procedure PlotDot;
  1160.   var Dot: TRect;
  1161.   begin
  1162.     FPlot.Canvas.Brush.Color := Color;
  1163.     if (X < Xll)  and FXAxis.LowLimit.Visible  then
  1164.         FPlot.Canvas.Brush.Color := FXAxis.LowLimit.AlarmColor;
  1165.     if (X > Xhl) and FXAxis.HighLimit.Visible then
  1166.         FPlot.Canvas.Brush.Color := FXAxis.HighLimit.AlarmColor;
  1167.     if (Y < Yll)  and FYAxis.LowLimit.Visible  then
  1168.         FPlot.Canvas.Brush.Color := FYAxis.LowLimit.AlarmColor;
  1169.     if (Y > Yhl) and FYAxis.HighLimit.Visible then
  1170.         FPlot.Canvas.Brush.Color := FYAxis.HighLimit.AlarmColor;
  1171.     Dot.Left   := L   - S      + Xpix;
  1172.     Dot.Right  := L   - S + S2 + Xpix;
  1173.     Dot.Bottom := B+1 + S      - Ypix;
  1174.     Dot.Top    := B+1 + S - S2 - Ypix;
  1175.     FPlot.Canvas.FillRect(Dot);
  1176.     FPlot.Canvas.Brush.Color := FPlotAreaColor;
  1177.   end;
  1178. {MWMWMWMW}
  1179.   procedure PlotBar;
  1180.   begin
  1181.     if (X < Xll) and FXAxis.LowLimit.Visible then
  1182.         FPlot.Canvas.Pen.Color := FXAxis.LowLimit.AlarmColor;
  1183.     if (X > Xhl) and FXAxis.HighLimit.Visible then
  1184.         FPlot.Canvas.Pen.Color := FXAxis.HighLimit.AlarmColor;
  1185.     FPlot.Canvas.MoveTo(L + Xpix, B - Round(-FYAxis.Min * Yqnt));
  1186.     FPlot.Canvas.LineTo(L + Xpix, B - Ypix);
  1187.     FPlot.Canvas.Pen.Color := FYAxis.LowLimit.AlarmColor;
  1188.     if (Y < Yll) and FYAxis.LowLimit.Visible then
  1189.         if Yll < 0 then begin
  1190.               FPlot.Canvas.MoveTo(L + Xpix, B - Ypix);
  1191.               FPlot.Canvas.LineTo(L + Xpix, B - Round((Yll - FYAxis.Min) * Yqnt));
  1192.             end
  1193.           else begin
  1194.               FPlot.Canvas.MoveTo(L + Xpix, B - Round(-FYAxis.Min * Yqnt));
  1195.               FPlot.Canvas.LineTo(L + Xpix, B - Ypix);
  1196.             end
  1197.       else
  1198.         if (Y > Yll) and (Yll > 0) then begin
  1199.               FPlot.Canvas.MoveTo(L + Xpix, B - Round(-FYAxis.Min * Yqnt));
  1200.               FPlot.Canvas.LineTo(L + Xpix, B - Round((Yll - FYAxis.Min) * Yqnt));
  1201.             end;
  1202.     FPlot.Canvas.Pen.Color := FYAxis.HighLimit.AlarmColor;
  1203.     if (Y > Yhl) and FYAxis.HighLimit.Visible then
  1204.         if Yhl > 0 then begin
  1205.               FPlot.Canvas.MoveTo(L + Xpix, B - Ypix);
  1206.               FPlot.Canvas.LineTo(L + Xpix, B - Round((Yhl - FYAxis.Min) * Yqnt));
  1207.             end
  1208.           else begin
  1209.               FPlot.Canvas.MoveTo(L + Xpix, B - Round(-FYAxis.Min * Yqnt));
  1210.               FPlot.Canvas.LineTo(L + Xpix, B - Ypix);
  1211.             end
  1212.       else
  1213.         if (Y < Yhl) and (Yhl < 0) then begin
  1214.               FPlot.Canvas.MoveTo(L + Xpix, B - Round(-FYAxis.Min * Yqnt));
  1215.               FPlot.Canvas.LineTo(L + Xpix, B - Round((Yhl - FYAxis.Min) * Yqnt));
  1216.             end;
  1217.   end;
  1218. {MWMWMWMW}
  1219.   procedure PlotLine;
  1220.     procedure Swap(var Xa, Ya, Xb, Yb: Extended);
  1221.     var Xc, Yc: Extended;
  1222.     begin
  1223.       Xc := Xa;  Yc := Ya;
  1224.       Xa := Xb;  Ya := Yb;
  1225.       Xb := Xc;  Yb := Yc;
  1226.     end;
  1227.   var n         : Integer;
  1228.       Xavg, Yavg: Extended;
  1229.       Xx, Yy    : array[0..5] of Extended;
  1230.   begin
  1231.     if FClr then begin
  1232.           FPlot.Canvas.MoveTo(L + Xpix, B+1 - Ypix);
  1233.           FClr := False;
  1234.         end
  1235.       else begin
  1236.           if Ynew < Yold then Swap(Xnew, Ynew, Xold, Yold);
  1237.           Xx[0] := Xold; Yy[0] := Yold;
  1238.           Xx[5] := Xnew; Yy[5] := Ynew;
  1239.           Yy[1] := Yll;
  1240.           try Xx[1] := Xold + (Xnew - Xold) * (Yy[1] - Yold) / (Ynew - Yold);
  1241.           except on EZeroDivide do Xx[1] := (Xnew - Xold) / 2; end;
  1242.           Xx[2] := Xll;
  1243.           try Yy[2] := Yold + (Ynew - Yold) * (Xx[2] - Xold) / (Xnew - Xold);
  1244.           except on EZeroDivide do Yy[2] := (Ynew - Yold) / 2; end;
  1245.           Xx[3] := Xhl;
  1246.           try Yy[3] := Yold + (Ynew - Yold) * (Xx[3] - Xold) / (Xnew - Xold);
  1247.           except on EZeroDivide do Yy[3] := (Ynew - Yold) / 2; end;
  1248.           Yy[4] := Yhl;
  1249.           try Xx[4] := Xold + (Xnew - Xold) * (Yy[4] - Yold) / (Ynew - Yold);
  1250.           except on EZeroDivide do Xx[4] := (Xnew - Xold) / 2; end;
  1251.           // Sort dots descending by Y-value
  1252.           if Yy[1] > Yy[2] then Swap(Xx[1], Yy[1], Xx[2], Yy[2]);
  1253.           if Yy[2] > Yy[3] then Swap(Xx[2], Yy[2], Xx[3], Yy[3]);
  1254.           if Yy[3] > Yy[4] then Swap(Xx[3], Yy[3], Xx[4], Yy[4]);
  1255.           if Yy[1] > Yy[2] then Swap(Xx[1], Yy[1], Xx[2], Yy[2]);
  1256.           if Yy[2] > Yy[3] then Swap(Xx[2], Yy[2], Xx[3], Yy[3]);
  1257.           if Yy[1] > Yy[2] then Swap(Xx[1], Yy[1], Xx[2], Yy[2]);
  1258.           if Yold >= Yy[1] then begin Xx[1] := Xold; Yy[1] := Yold; end;
  1259.           if Yold >= Yy[2] then begin Xx[2] := Xold; Yy[2] := Yold; end;
  1260.           if Yold >= Yy[3] then begin Xx[3] := Xold; Yy[3] := Yold; end;
  1261.           if Yold >= Yy[4] then begin Xx[4] := Xold; Yy[4] := Yold; end;
  1262.           if Ynew <= Yy[1] then begin Xx[1] := Xnew; Yy[1] := Ynew; end;
  1263.           if Ynew <= Yy[2] then begin Xx[2] := Xnew; Yy[2] := Ynew; end;
  1264.           if Ynew <= Yy[3] then begin Xx[3] := Xnew; Yy[3] := Ynew; end;
  1265.           if Ynew <= Yy[4] then begin Xx[4] := Xnew; Yy[4] := Ynew; end;
  1266.           // Draw partial lines
  1267.           for n := 1 to 5 do begin
  1268.           if (Xx[n - 1] = Xx[n]) and (Yy[n - 1] = Yy[n]) then continue;
  1269.               Xavg := (Xx[n - 1] + Xx[n]) / 2;
  1270.               Yavg := (Yy[n - 1] + Yy[n]) / 2;
  1271.               if (Yavg < Yll) and FYAxis.LowLimit.Visible
  1272.                 then FPlot.Canvas.Pen.Color := FYAxis.LowLimit.AlarmColor
  1273.                 else if (Yavg > Yhl) and FYAxis.HighLimit.Visible
  1274.                        then FPlot.Canvas.Pen.Color := FYAxis.HighLimit.AlarmColor
  1275.                        else if (Xavg < Xll) and FXAxis.LowLimit.Visible
  1276.                               then FPlot.Canvas.Pen.Color := FXAxis.LowLimit.AlarmColor
  1277.                               else if (Xavg > Xhl) and FXAxis.HighLimit.Visible
  1278.                                      then FPlot.Canvas.Pen.Color := FXAxis.HighLimit.AlarmColor
  1279.                                      else FPlot.Canvas.Pen.Color := Color;
  1280.               FPlot.Canvas.MoveTo(L + Round((Xx[n - 1] - FXAxis.Min) * Xqnt),
  1281.                                   B - Round((Yy[n - 1] - FYAxis.Min) * Yqnt));
  1282.               FPlot.Canvas.LineTo(L + Round((Xx[n]     - FXAxis.Min) * Xqnt),
  1283.                                   B - Round((Yy[n]     - FYAxis.Min) * Yqnt));
  1284.             end;
  1285.         end;
  1286.   end;
  1287. {MWMWMWMW}
  1288. begin
  1289.   L  := FRPlot.Left;
  1290.   B  := FRPlot.Bottom-1;
  1291.   S  := FPlotPen.Width div 2;
  1292.   S2 := FPlotPen.Width;
  1293.   FPlot.Canvas.Pen.Assign(FPlotPen);
  1294.   FPlot.Canvas.Pen.Color := Color;
  1295.   if FLayerOptions then begin
  1296.         FPlotMode := FLayerOpt[Layer].PlotMode;
  1297.         if FPlotMode = pmDot then begin
  1298.               S  := (FLayerOpt[Layer].PenWidth) div 2;
  1299.               S2 :=  FLayerOpt[Layer].PenWidth;
  1300.             end
  1301.           else
  1302.             FPlot.Canvas.Pen.Width := FLayerOpt[Layer].PenWidth;
  1303.       end;
  1304.   Xnew := X;
  1305.   Ynew := Y;
  1306.   Xpix := Round((Xnew - FXAxis.Min) * Xqnt);
  1307.   Ypix := Round((Ynew - FYAxis.Min) * Yqnt);
  1308.   Xold := LastXDrawn[Layer];
  1309.   Yold := LastYDrawn[Layer];
  1310.   LastXDrawn[Layer] := Xnew;
  1311.   LastYDrawn[Layer] := Ynew;
  1312.   Xll := FXAxis.LowLimit.Value;
  1313.   Xhl := FXAxis.HighLimit.Value;
  1314.   Yll := FYAxis.LowLimit.Value;
  1315.   Yhl := FYAxis.HighLimit.Value;
  1316.   case FPlotMode of
  1317.     pmDot : PlotDot;
  1318.     pmLine: PlotLine;
  1319.     pmBar : PlotBar;
  1320.   end;
  1321.   if not FFreeze then FBorder.Canvas.CopyRect(FRPlot, FPlot.Canvas, FRPlot);
  1322. end;
  1323. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1324.  
  1325. procedure Tth2DGraph.Redraw;
  1326.   function GetMax(V1, V2: Integer): Integer;
  1327.   begin
  1328.     if V1 > V2 then Result := V1
  1329.                else Result := V2;
  1330.   end;
  1331. var i, j     : Integer;
  1332.     tmpFreeze: Boolean;
  1333.     tmpLimit : Extended;
  1334.     tmpXMarg : Integer;
  1335.     tmpYMarg : Integer;
  1336.     ACanvas  : TCanvas;
  1337.  
  1338.     BMP: TBitmap;
  1339.     R: TRect;
  1340.     Color1, Color2: TColor;
  1341.     R1, G1, B1: Byte;
  1342.     R2, G2, B2: Byte;
  1343.     R3, G3, B3: Byte;
  1344.  
  1345. begin
  1346.   if (csDesigning in ComponentState) then ACanvas := Canvas
  1347.                                      else ACanvas := FBorder.Canvas;
  1348.   FCursorOldX := -1;
  1349.   FCursorOldY := -1;
  1350.   ACanvas.Font.Assign(FTitleFont);
  1351.   // Adjust Margins
  1352.   if FXAxis.Visible then tmpXMarg := FXAxis.MarginBottom else tmpXMarg := 0;
  1353.   if FYAxis.Visible then tmpYMarg := FYAxis.MarginBottom else tmpYMarg := 0;
  1354.   FMarginBottom := GetMax(tmpXMarg, tmpYMarg);
  1355.   if FXAxis.Visible then tmpXMarg := FXAxis.MarginLeft   else tmpXMarg := 0;
  1356.   if FYAxis.Visible then tmpYMarg := FYAxis.MarginLeft   else tmpYMarg := 0;
  1357.   FMarginLeft   := GetMax(tmpXMarg, tmpYMarg);
  1358.   if FXAxis.Visible then tmpXMarg := FXAxis.MarginRight  else tmpXMarg := 0;
  1359.   FMarginRight  := tmpXMarg;
  1360.   if FYAxis.Visible then tmpYMarg := FYAxis.MarginTop    else tmpYMarg := 0;
  1361.   if Length(FTitle) <> 0
  1362.     then FMarginTop := GetMax(ACanvas.TextHeight(FTitle), tmpYMarg)
  1363.     else FMarginTop := tmpYMarg;
  1364.   Inc(FMarginBottom, FMargin);
  1365.   Inc(FMarginLeft,   FMargin);
  1366.   Inc(FMarginRight,  FMargin);
  1367.   Inc(FMarginTop,    FMargin);
  1368.   // Refresh proportional Value
  1369.   AdjustR2Dimension;
  1370.   // FPlot bitmap size
  1371.   FPlot.Width  := Width  - 2 * BevelWidth;
  1372.   FPlot.Height := Height - 2 * BevelWidth;
  1373.   // FRBorder is the whole visible area of the Panel (Border)
  1374.   FRBorder.Left   := 2 * BevelWidth;
  1375.   FRBorder.Top    := 2 * BevelWidth;
  1376.   FRBorder.Right  := Width  - 2 * BevelWidth;
  1377.   FRBorder.Bottom := Height - 2 * BevelWidth;
  1378.   // FRPlot is the part where the plotting is done
  1379.   FRPlot.Left   := FRBorder.Left   + FMarginLeft;
  1380.   FRPlot.Top    := FRBorder.Top    + FMarginTop;
  1381.   FRPlot.Right  := FRBorder.Right  - FMarginRight;
  1382.   FRPlot.Bottom := FRBorder.Bottom - FMarginBottom;
  1383.   // Draws the window for the graph
  1384.   if ACanvas = FBorder.Canvas then begin
  1385.         FBorder.Width  := Width  - 2 * BevelWidth;
  1386.         FBorder.Height := Height - 2 * BevelWidth;
  1387.       end;
  1388.   // Draws border
  1389.   if FBorderGradient.Enable then
  1390.  
  1391. ////// vykreslovat gradient jen pri zmene
  1392.  
  1393.       FBorderGradient.Draw(ACanvas, FRBorder)
  1394.     else begin
  1395.         ACanvas.Brush.Color := Color;
  1396.         ACanvas.FillRect(FRBorder);
  1397.       end;  
  1398.   // Draws plot area
  1399.   if FPlotAreaGradient.Enable then
  1400.  
  1401. ////// vykreslovat gradient jen pri zmene
  1402.  
  1403.       FPlotAreaGradient.Draw(ACanvas, FRPlot)
  1404.     else
  1405.       if FPlotAreaColor = clNone then
  1406.           ACanvas.CopyRect(FRPlot, FBorder.Canvas, FRPlot)
  1407.         else begin
  1408.             ACanvas.Brush.Color := FPlotAreaColor;
  1409.             ACanvas.FillRect(FRPlot);
  1410.           end;
  1411.   // Graph title - font assigned hereinbefore
  1412.   if FTitle <> '' then
  1413.         ACanvas.Textout(FRPlot.Left + (FRPlot.Right-1 - FRPlot.Left - ACanvas.TextWidth(FTitle)) div 2,
  1414.                         (FRPlot.Top + FRBorder.Top - ACanvas.TextHeight(FTitle)) div 2, FTitle);
  1415.   // Draws grids
  1416.   ACanvas.Pen.Assign(FGridPen);
  1417.   // Y-axis (vertical) lines
  1418.   YAxis.Length := FRPlot.Bottom-1 - FRPlot.Top;
  1419.   if GridShow then
  1420.       for i := 0 to FXAxis.Divisions do begin
  1421.           ACanvas.MoveTo(Round((i * (FRPlot.Right-1 - FRPlot.Left)) / FXAxis.Divisions) + FRPlot.Left, FRPlot.Top);
  1422.           ACanvas.LineTo(Round((i * (FRPlot.Right-1 - FRPlot.Left)) / FXAxis.Divisions) + FRPlot.Left, FRPlot.Bottom-1);
  1423.         end;
  1424.   // X-axis (horizontal) lines
  1425.   XAxis.Length := FRPlot.Right-1 - FRPlot.Left;
  1426.   if GridShow then
  1427.       for i := 0 to FYAxis.Divisions do begin
  1428.           ACanvas.MoveTo(FRPlot.Left,    FRPlot.Bottom-1 - Round((i * (FRPlot.Bottom-1 - FRPlot.Top)) / FYAxis.Divisions));
  1429.           ACanvas.LineTo(FRPlot.Right-1, FRPlot.Bottom-1 - Round((i * (FRPlot.Bottom-1 - FRPlot.Top)) / FYAxis.Divisions));
  1430.         end;
  1431.   // Draw axes
  1432.   XAxis.Draw(ACanvas, FRPlot.Left, FRPlot.Bottom-1);
  1433.   YAxis.Draw(ACanvas, FRPlot.Left, FRPlot.Bottom-1);
  1434.   // Draw limits
  1435.   if FXAxis.HighLimit.Visible then begin
  1436.         tmpLimit := FXAxis.HighLimit.Value;
  1437.         if (tmpLimit < FXAxis.Max) and (tmpLimit > FXAxis.Min) then begin
  1438.               ACanvas.Pen.Assign(FXAxis.HighLimit.Pen);
  1439.               ACanvas.MoveTo(FRPlot.Left+1 + Round((tmpLimit - FXAxis.Min) * Xqnt), FRPlot.Top);
  1440.               ACanvas.LineTo(FRPlot.Left+1 + Round((tmpLimit - FXAxis.Min) * Xqnt), FRPlot.Bottom-1);
  1441.             end;
  1442.       end;
  1443.   if FXAxis.LowLimit.Visible then begin
  1444.         tmpLimit := FXAxis.LowLimit.Value;
  1445.         if (tmpLimit < FXAxis.Max) and (tmpLimit > FXAxis.Min) then begin
  1446.               ACanvas.Pen.Assign(FXAxis.LowLimit.Pen);
  1447.               ACanvas.MoveTo(FRPlot.Left + Round((tmpLimit - FXAxis.Min) * Xqnt), FRPlot.Top);
  1448.               ACanvas.LineTo(FRPlot.Left + Round((tmpLimit - FXAxis.Min) * Xqnt), FRPlot.Bottom-1);
  1449.             end;
  1450.       end;
  1451.   if FYAxis.HighLimit.Visible then begin
  1452.         tmpLimit := FYAxis.HighLimit.Value;
  1453.         if (tmpLimit < FYAxis.Max) and (tmpLimit > FYAxis.Min) then begin
  1454.               ACanvas.Pen.Assign(FYAxis.HighLimit.Pen);
  1455.               ACanvas.MoveTo(FRPlot.Left,    FRPlot.Bottom-1 - Round((tmpLimit - FYAxis.Min) * Yqnt));
  1456.               ACanvas.LineTo(FRPlot.Right-1, FRPlot.Bottom-1 - Round((tmpLimit - FYAxis.Min) * Yqnt));
  1457.             end;
  1458.       end;
  1459.   if FYAxis.LowLimit.Visible then begin
  1460.         tmpLimit := FYAxis.LowLimit.Value;
  1461.         if (tmpLimit < FYAxis.Max) and (tmpLimit > FYAxis.Min) then begin
  1462.               ACanvas.Pen.Assign(FYAxis.LowLimit.Pen);
  1463.               ACanvas.MoveTo(FRPlot.Left,    FRPlot.Bottom-1 - Round((tmpLimit - FYAxis.Min) * Yqnt));
  1464.               ACanvas.LineTo(FRPlot.Right-1, FRPlot.Bottom-1 - Round((tmpLimit - FYAxis.Min) * Yqnt));
  1465.             end;
  1466.       end;
  1467.   ACanvas.Pen.Assign(FGridPen); // Without this line is graph no correct repainted
  1468.   // Plot data
  1469.   if not(csDesigning in ComponentState) then begin
  1470.         FPlot.Canvas.CopyRect(FRPlot, ACanvas, FRPlot);
  1471.         tmpFreeze := FFreeze;
  1472.         FFreeze := True;
  1473.         for j := 1 to MAX_CURVES do
  1474.             if FDataLength[j] > 1 then begin
  1475.                   FClr := True;
  1476.                   for i := 1 to FDataLength[j] - 1 do
  1477.                     PlotData(FDataArray[j, i].X, FDataArray[j, i].Y, FDataArray[j, i].C, j);
  1478.                 end;
  1479.         FFreeze := tmpFreeze;
  1480.         FBorder.Canvas.CopyRect(FRPlot, FPlot.Canvas, FRPlot);
  1481.         if not FFreeze then Canvas.CopyRect(FRBorder, FBorder.Canvas, FRBorder);
  1482.         MouseMove([], ScreenToClient(Mouse.CursorPos).X, ScreenToClient(Mouse.CursorPos).Y);
  1483.       end;
  1484. end;
  1485. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1486.  
  1487. procedure Tth2DGraph.SetPlotAreaColor(const Value: Tcolor);
  1488. begin
  1489.   if FPlotAreaColor = Value then Exit;
  1490.   FPlotAreaColor := Value;
  1491.   Redraw;
  1492. end;
  1493. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1494.  
  1495. procedure Tth2DGraph.SetBorderGradient(const Value: TGradient);
  1496. begin
  1497.   if FBorderGradient = Value then Exit;
  1498.   FBorderGradient.Assign(Value);
  1499.   Redraw;
  1500. end;
  1501. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1502.  
  1503. procedure Tth2DGraph.SetCursorShow(const Value: Boolean);
  1504. begin
  1505.   if FCursorShow = Value then Exit;
  1506.   FCursorShow := Value;
  1507.   Redraw;
  1508. end;
  1509. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1510.  
  1511. procedure Tth2DGraph.SetCursorShowValues(const Value: Boolean);
  1512. begin
  1513.   if FCursorShowValues = Value then Exit;
  1514.   FCursorShowValues := Value;
  1515.   Redraw;
  1516. end;
  1517. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1518.  
  1519. procedure Tth2DGraph.SetCurValFont(const Value: TFont);
  1520. begin
  1521.   if FCurValFont = Value then Exit;
  1522.   FCurValFont.Assign(Value);
  1523.   Redraw;
  1524. end;
  1525. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1526.  
  1527. procedure Tth2DGraph.SetCurValPosLeft(const Value: Integer);
  1528. begin
  1529.   if FCurValPosLeft = Value then Exit;
  1530.   FCurValPosLeft := Value;
  1531.   Redraw;
  1532. end;
  1533. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1534.  
  1535. procedure Tth2DGraph.SetCurValPosTop(const Value: Integer);
  1536. begin
  1537.   if FCurValPosTop = Value then Exit;
  1538.   FCurValPosTop := Value;
  1539.   Redraw;
  1540. end;
  1541. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1542.  
  1543. procedure Tth2DGraph.SetFXAxis(const Value: TAxis);
  1544. begin
  1545.   if FXAxis = Value then Exit;
  1546.   FXAxis.Assign(Value);
  1547.   Redraw;
  1548. end;
  1549. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1550.  
  1551. procedure Tth2DGraph.SetFYAxis(const Value: TAxis);
  1552. begin
  1553.   if FYAxis = Value then Exit;
  1554.   FYAxis.Assign(Value);
  1555.   Redraw;
  1556. end;
  1557. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1558.  
  1559. procedure Tth2DGraph.SetGridShow(const Value: Boolean);
  1560. begin
  1561.   if FGridShow = Value then Exit;
  1562.   FGridShow := Value;
  1563.   Redraw;
  1564. end;
  1565. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1566.  
  1567. procedure Tth2DGraph.SetGridPen(const Value: TPen);
  1568. begin
  1569.   if FGridPen = Value then Exit;
  1570.   FGridPen.Assign(Value);
  1571.   Redraw;
  1572. end;
  1573. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1574.  
  1575. procedure Tth2DGraph.SetLayerOptions(const Value: Boolean);
  1576. begin
  1577.   if FLayerOptions = Value then Exit;
  1578.   FLayerOptions := Value;
  1579. end;
  1580. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1581.  
  1582. procedure Tth2DGraph.SetMargin(const Value: Integer);
  1583. begin
  1584.   if FMargin = Value then Exit;
  1585.   FMargin := Value;
  1586.   Redraw;
  1587. end;
  1588. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1589.  
  1590. procedure Tth2DGraph.SetPlotAreaGradient(const Value: TGradient);
  1591. begin
  1592.   if FPlotAreaGradient = Value then Exit;
  1593.   FPlotAreaGradient.Assign(Value);
  1594.   Redraw;
  1595. end;
  1596. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1597.  
  1598. procedure Tth2DGraph.SetPlotMode(const Value: TPlotMode);
  1599. begin
  1600.   if FPlotMode = Value then Exit;
  1601.   FPlotMode := Value;
  1602.   Redraw;
  1603. end;
  1604. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1605.  
  1606. procedure Tth2DGraph.SetPlotPen(const Value: TPen);
  1607. begin
  1608.   if FPlotPen = Value then Exit;
  1609.   FPlotPen.Assign(Value);
  1610.   Redraw;
  1611. end;
  1612. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1613.  
  1614. procedure Tth2DGraph.SetTitle(const Value: String);
  1615. begin
  1616.   if FTitle = Value then Exit;
  1617.   FTitle := Value;
  1618.   Redraw;
  1619. end;
  1620. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1621.  
  1622. procedure Tth2DGraph.SetTitleFont(const Value: TFont);
  1623. begin
  1624.   if FTitleFont = Value then Exit;
  1625.   FTitleFont.Assign(Value);
  1626.   Redraw;
  1627. end;
  1628.  
  1629. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1630. {MWM  Tth2DGraph - protected metods  MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1631. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1632.  
  1633. procedure Tth2DGraph.MouseMove(Shift: TShiftState; X, Y: Integer);
  1634. var NeedRepaint: Boolean;
  1635.     WX, WY     : Extended;
  1636.   procedure DeleteOldCursor;
  1637.   begin
  1638.     if (FCursorOldX <> -1) and (FCursorOldY <> -1) then begin
  1639.           FPlot.Canvas.MoveTo(FCursorOldX, 0);
  1640.           FPlot.Canvas.LineTo(FCursorOldX, FPlot.Height-1);
  1641.           FPlot.Canvas.MoveTo(0, FCursorOldY);
  1642.           FPlot.Canvas.LineTo(FPlot.Width-1, FCursorOldY);
  1643.           NeedRepaint := True;
  1644.         end;
  1645.   end;
  1646. begin
  1647.   if FCursorShow then begin
  1648.         NeedRepaint := False;
  1649.         FPlot.Canvas.Pen.Width := 1;
  1650.         FPlot.Canvas.Pen.Mode := pmNot;
  1651.         if Cursor <> crNone then FCursorTmp := Cursor;
  1652.         if (X < FRPlot.Left) or (X > FRPlot.Right-1) or (Y < FRPlot.Top) or (Y > FRPlot.Bottom-1) then begin
  1653.               Cursor := FCursorTmp;
  1654.               DeleteOldCursor;
  1655.               FCursorOldX := -1;
  1656.               FCursorOldY := -1;
  1657.             end
  1658.           else begin
  1659.               Cursor := crNone;
  1660.               DeleteOldCursor;
  1661.               FPlot.Canvas.MoveTo(X, 0);
  1662.               FPlot.Canvas.LineTo(X, FPlot.Height-1);
  1663.               FPlot.Canvas.MoveTo(0, Y);
  1664.               FPlot.Canvas.LineTo(FPlot.Width-1, Y);
  1665.               NeedRepaint := True;
  1666.               FCursorOldX := X;
  1667.               FCursorOldY := Y;
  1668.             end;
  1669.         if NeedRepaint then begin
  1670.               FBorder.Canvas.CopyRect(FRPlot, FPlot.Canvas, FRPlot);
  1671.               Canvas.CopyRect(FRBorder, FBorder.Canvas, FRBorder);
  1672.               if FCursorShowValues then begin
  1673.                     ConvertS2W(X, Y, WX, WY);
  1674.                     Canvas.Font.Assign(FCurValFont);
  1675.                     if (FCursorOldX <> -1) and (FCursorOldY <> -1)
  1676.                       then Canvas.TextOut(FRPlot.Left + FCurValPosLeft, FRPlot.Top + FCurValPosTop,
  1677.                                           'X = ' + FloatToStr(WX) + ENDL + 'Y = ' + FloatToStr(WY))
  1678.                       else Canvas.TextOut(FRPlot.Left + FCurValPosLeft, FRPlot.Top + FCurValPosTop,
  1679.                                           'X = ???' + ENDL + 'Y = ???');
  1680.                   end;
  1681.             end;
  1682.       end;
  1683.   inherited MouseMove(Shift, X, Y);
  1684. end;
  1685.  
  1686. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1687. {MWM  Tth2DGraph - public metods  WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1688. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1689.  
  1690. constructor Tth2DGraph.Create;
  1691. var n: Integer;
  1692. begin
  1693.   inherited Create(AOwner);
  1694.   // Global panel default settings
  1695. //  BevelInner := bvRaised;
  1696. //  BevelOuter := bvLowered;
  1697. //  BevelWidth := 2;
  1698.   Caption    := '';
  1699.   Height     := 200;
  1700.   ParentFont := False;
  1701.   Width      := 300;
  1702.   // Create all dynamic structures
  1703.   FBorder           := TBitmap.Create;
  1704.   FBorderGradient   := TGradient.Create;
  1705.   FCurValFont       := TFont.Create;
  1706.   FGridPen          := TPen.Create;
  1707.   FPlot             := TBitmap.Create;
  1708.   FPlotAreaGradient := TGradient.Create;
  1709.   FPlotPen          := TPen.Create;
  1710.   FTitleFont        := TFont.Create;
  1711.   FXAxis            := TAxis.Create;
  1712.   FYAxis            := TAxis.Create;
  1713.   // Events assignment
  1714.   FBorderGradient.OnChange      := DoPaint;
  1715.   FCurValFont.OnChange          := DoPaint;
  1716.   FGridPen.OnChange             := DoPaint;
  1717.   FPlotAreaGradient.OnChange    := DoPaint;
  1718.   FPlotPen.OnChange             := DoPaint;
  1719.   FTitleFont.OnChange           := DoPaint;
  1720.   FXAxis.OnChange               := DoPaint;
  1721.   FYAxis.OnChange               := DoPaint;
  1722.   FXAxis.HighLimit.OnChange     := ChangedLimits;
  1723.   FYAxis.HighLimit.OnChange     := ChangedLimits;
  1724.   FXAxis.HighLimit.Pen.OnChange := ChangedLimits;
  1725.   FYAxis.HighLimit.Pen.OnChange := ChangedLimits;
  1726.   FXAxis.LowLimit.OnChange      := ChangedLimits;
  1727.   FYAxis.LowLimit.OnChange      := ChangedLimits;
  1728.   FXAxis.LowLimit.Pen.OnChange  := ChangedLimits;
  1729.   FYAxis.LowLimit.Pen.OnChange  := ChangedLimits;
  1730.   FXAxis.MarksFont.OnChange     := DoPaint;
  1731.   FYAxis.MarksFont.OnChange     := DoPaint;
  1732.   FXAxis.NameFont.OnChange      := DoPaint;
  1733.   FYAxis.NameFont.OnChange      := DoPaint;
  1734.   FXAxis.Pen.OnChange           := DoPaint;
  1735.   FYAxis.Pen.OnChange           := DoPaint;
  1736.   // Default distances between graph-edges and panel borders
  1737.   FMargin       := 10;
  1738.   FMarginLeft   := FMargin + 2 * BevelWidth;
  1739.   FMarginTop    := FMargin + 2 * BevelWidth;
  1740.   FMarginBottom := FMargin + 2 * BevelWidth;
  1741.   FMarginRight  := FMargin + 2 * BevelWidth;
  1742.   // Values referred to axes
  1743.   FXAxis.HighLimit.Visible := True;
  1744.   FYAxis.HighLimit.Visible := True;
  1745.   FXAxis.LowLimit.Visible  := True;
  1746.   FYAxis.LowLimit.Visible  := True;
  1747.   FXAxis.Orientation       := orHorizontal;
  1748.   FYAxis.Orientation       := orVertical;
  1749.   // Other settings
  1750.   FCursorOldX       := -1;
  1751.   FCursorOldY       := -1;
  1752.   FCursorShow       := True;
  1753.   FCursorShowValues := True;
  1754.   FCurValPosLeft    := 10;
  1755.   FCurValPosTop     := 5;
  1756.   FGridShow         := True;
  1757.   FLayerOptions     := False;
  1758.   FPlotMode         := pmLine;
  1759.   FTitle            := '> Graph title <';
  1760.   for n := 1 to MAX_CURVES do begin
  1761.       FLayerOpt[n].PlotMode := FPlotMode;
  1762.       FLayerOpt[n].PenWidth := 1;
  1763.       FDataLength[n]        := 1;
  1764.       SetLength(FDataArray[n], 1);
  1765.     end;
  1766.   // Graph and axes styles and colors
  1767.   FPlotAreaColor               := clBase;
  1768.   FBorderGradient.ColorStart   := $E6F3F3;
  1769.   FBorderGradient.ColorStop    := $9ECFCF;
  1770.   FGridPen.Color               := $999FFF;
  1771.   FGridPen.Style              := psDot;
  1772.   FPlotAreaGradient.ColorStart := $8EBFDB;
  1773.   FPlotAreaGradient.ColorStop  := $B6C3EF;
  1774.   FPlotAreaGradient.Direction  := diLeftRight;
  1775.   FPlotPen.Color               := clMaroon;
  1776.   FTitleFont.Color             := $808040;
  1777.   FXAxis.HighLimit.Pen.Color   := clYellow;
  1778.   FXAxis.HighLimit.AlarmColor  := clYellow;
  1779.   FXAxis.LowLimit.Pen.Color    := clLime;
  1780.   FXAxis.LowLimit.AlarmColor   := clLime;
  1781.   FYAxis.HighLimit.Pen.Color   := clRed;
  1782.   FYAxis.HighLimit.AlarmColor  := clRed;
  1783.   FYAxis.LowLimit.Pen.Color    := clFuchsia;
  1784.   FYAxis.LowLimit.AlarmColor   := clFuchsia;
  1785.   Redraw;
  1786. end;
  1787. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1788.  
  1789. destructor Tth2DGraph.Destroy;
  1790. begin
  1791.   if Assigned(FYAxis)            then FreeAndNil(FYAxis);
  1792.   if Assigned(FXAxis)            then FreeAndNil(FXAxis);
  1793.   if Assigned(FTitleFont)        then FreeAndNil(FTitleFont);
  1794.   if Assigned(FPlotPen)          then FreeAndNil(FPlotPen);
  1795.   if Assigned(FPlotAreaGradient) then FreeAndNil(FPlotAreaGradient);
  1796.   if Assigned(FPlot)             then FreeAndNil(FPlot);
  1797.   if Assigned(FGridPen)          then FreeAndNil(FGridPen);
  1798.   if Assigned(FCurValFont)       then FreeAndNil(FCurValFont);
  1799.   if Assigned(FBorderGradient)   then FreeAndNil(FBorderGradient);
  1800.   if Assigned(FBorder)           then FreeAndNil(FBorder);
  1801.   inherited Destroy;
  1802. end;
  1803. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1804.  
  1805. procedure Tth2DGraph.AddXY(X, Y: Extended);
  1806. var Color: TColor;
  1807.     Layer: Integer;
  1808. begin
  1809.   Layer := 1;
  1810.   Color := FPlotPen.Color;
  1811.   FLayerOptions := False;
  1812.   if FDataLength[Layer] = 1 then FClr := True;
  1813.   Inc(FDataLength[Layer]);
  1814.   SetLength(FDataArray[Layer], FDataLength[Layer]);
  1815.   FDataArray[Layer, FDataLength[Layer] - 1].X := X;
  1816.   FDataArray[Layer, FDataLength[Layer] - 1].Y := Y;
  1817.   FDataArray[Layer, FDataLength[Layer] - 1].C := Color;
  1818.   PlotData(X, Y, Color, Layer);
  1819.   if not FFreeze then Canvas.CopyRect(FRBorder, FBorder.Canvas, FRBorder);
  1820. end;
  1821. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1822.  
  1823. procedure Tth2DGraph.AddXY(X, Y: Extended; Color: TColor; Layer: Integer = 1);
  1824. begin
  1825.   if (Layer < 1) or (Layer > MAX_CURVES) then Exit;
  1826.   if FDatalength[Layer] = 1 then FClr := True;
  1827.   Inc(FDataLength[Layer]);
  1828.   SetLength(FDataArray[Layer], FDataLength[Layer]);
  1829.   FDataArray[Layer, FDataLength[Layer] - 1].X := X;
  1830.   FDataArray[Layer, FDataLength[Layer] - 1].Y := Y;
  1831.   FDataArray[Layer, FDataLength[Layer] - 1].C := Color;
  1832.   PlotData(X, Y, Color, Layer);
  1833.   if not FFreeze then Canvas.CopyRect(FRBorder, FBorder.Canvas, FRBorder);
  1834. end;
  1835. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1836. {
  1837. procedure Tth2DGraph.AntiAlias;
  1838. var n, cx, cy       : Integer;
  1839.     Rows, Cols      : Integer;
  1840.     totR, totG, totB: Integer;
  1841.     BigBMP, OutBMP  : TBitmap;
  1842.     Row1, Row2, Row3: PrgbArray;
  1843.     DestRow         : PrgbArray;
  1844.     Width, Height   : Integer;
  1845.     Rect            : TRect;
  1846. begin
  1847.   Width  := FBorder.Width;
  1848.   Height := FBorder.Height;
  1849.   BigBMP := TBitmap.Create;
  1850.   try
  1851.     BigBMP.Width       := 3 * Width;
  1852.     BigBMP.Height      := 3 * Height;
  1853. //    BigBMP.PixelFormat := pf32bit;
  1854.     Rect.TopLeft     := Point(0, 0);
  1855.     Rect.BottomRight := Point(FBorder.Width, FBorder.Height);
  1856.     BigBMP.Canvas.CopyRect(Rect, FBorder.Canvas, FRBorder);
  1857.     OutBMP := TBitmap.Create;
  1858.     try
  1859.       OutBMP.Width       := Width;
  1860.       OutBMP.Height      := Height;
  1861. //      OutBMP.PixelFormat := pf32bit;
  1862.       // for all rows
  1863.       for Rows := 0 to Height - 1 do begin
  1864.           cy := 3 * Rows;
  1865.           Row1    := BigBMP.ScanLine[cy];
  1866.           Row2    := BigBMP.ScanLine[cy + 1];
  1867.           Row3    := BigBMP.ScanLine[cy + 2];
  1868.           DestRow := OutBMP.ScanLine[Rows];
  1869.           // for all cols
  1870.           for Cols := 0 to Width - 1 do begin
  1871.               cx := 3 * Cols;
  1872.               totR := 0; totG := 0; totB := 0;
  1873.               // for all pixels i sample
  1874.               for n := 0 to 2 do begin
  1875.                   totR := totR + Row1[cx + n].RGBtRed   + Row2[cx + n].RGBtRed   + Row3[cx + n].RGBtRed;
  1876.                   totG := totG + Row1[cx + n].RGBtGreen + Row2[cx + n].RGBtGreen + Row3[cx + n].RGBtGreen;
  1877.                   totB := totB + Row1[cx + n].RGBtBlue  + Row2[cx + n].RGBtBlue  + Row3[cx + n].RGBtBlue;
  1878.                 end;
  1879.               DestRow[Cols].RGBtRed   := totR div 9;
  1880.               DestRow[Cols].RGBtGreen := totG div 9;
  1881.               DestRow[Cols].RGBtBlue  := totB div 9;
  1882.               DestRow[Cols].RGBtAny   := $00;
  1883.             end;
  1884.         end;
  1885.       FBorder.Canvas.CopyRect(FRBorder, OutBMP.Canvas, Rect);
  1886.       FPlot.Canvas.CopyRect(FRBorder, OutBMP.Canvas, Rect);
  1887.     finally
  1888.       OutBMP.Free;
  1889.     end;
  1890.   finally
  1891.     BigBMP.Free;
  1892.   end;
  1893. end;
  1894. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1895.  
  1896. procedure Tth2DGraph.AutoScale(Layer: Integer = 1);
  1897. var tmpMaxX, tmpMinX: Extended;
  1898.     tmpMaxY, tmpMinY: Extended;
  1899.     X, Y            : Extended;
  1900.     n               : Integer;
  1901. begin
  1902.   if (Layer < 1) or (Layer > MAX_CURVES) then Exit;
  1903.   if FDataLength[Layer] > 2 then begin
  1904.         tmpMaxX := FDataArray[Layer, 1].X;
  1905.         tmpMaxY := FDataArray[Layer, 1].Y;
  1906.         tmpMinX := tmpMaxX;
  1907.         tmpMinY := tmpMaxY;
  1908.         for n := 2 to FDataLength[Layer] - 1 do begin
  1909.             X := FDataArray[Layer, n].X;
  1910.             Y := FDataArray[Layer, n].Y;
  1911.             if X > tmpMaxX then tmpMaxX := X;
  1912.             if X < tmpMinX then tmpMinX := X;
  1913.             if Y > tmpMaxY then tmpMaxY := Y;
  1914.             if Y < tmpMinY then tmpMinY := Y;
  1915.           end;
  1916.         if tmpMaxX <= tmpMinX then begin
  1917.               if FXAxis.Divisions > 1 then
  1918.                   if tmpMinX <> 0 then begin
  1919.                         tmpMaxX := tmpMinX + Abs(tmpMinX) * (FXAxis.Divisions - 1);
  1920.                         tmpMinX := tmpMinX - Abs(tmpMinX);
  1921.                       end
  1922.                     else begin
  1923.                         tmpMaxX := FXAxis.Divisions - 1;
  1924.                         tmpMinX := - 1;
  1925.                       end
  1926.                 else
  1927.                   if tmpMinX <> 0 then tmpMaxX := tmpMinX + Abs(tmpMinX)
  1928.                                   else tmpMaxX := 1;
  1929.             end;
  1930.         if tmpMaxY <= tmpMinY then begin
  1931.               if FYAxis.Divisions > 1 then
  1932.                   if tmpMinY <> 0 then begin
  1933.                         tmpMaxY := tmpMinY + Abs(tmpMinY) * (FYAxis.Divisions - 1);
  1934.                         tmpMinY := tmpMinY - Abs(tmpMinY);
  1935.                       end
  1936.                     else begin
  1937.                         tmpMaxY := FYAxis.Divisions - 1;
  1938.                         FYAxis.Min := - 1;
  1939.                       end
  1940.                 else
  1941.                   if tmpMinY <> 0 then tmpMaxY := tmpMinY + Abs(tmpMinY)
  1942.                                   else tmpMaxY := 1;
  1943.             end;
  1944.         if tmpMaxX <> FXAxis.Max then FXAxis.Max := tmpMaxX;
  1945.         if tmpMinX <> FXAxis.Min then FXAxis.Min := tmpMinX;
  1946.         if tmpMaxY <> FYAxis.Max then FYAxis.Max := tmpMaxY;
  1947.         if tmpMinY <> FYAxis.Min then FYAxis.Min := tmpMinY;
  1948.       end;
  1949. end;
  1950. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1951.  
  1952. procedure Tth2DGraph.Clear;
  1953. var n: Integer;
  1954. begin
  1955.   FClr := True;
  1956.   for n := 1 to MAX_CURVES do begin
  1957.       FDataLength[n] := 1;
  1958.       FDataArray[n] := Copy(FDataArray[n], 0, 1);
  1959.       SetLength(FDataArray[n], 1);
  1960.     end;
  1961.   Redraw;
  1962. end;
  1963. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1964.  
  1965. function Tth2DGraph.ConvertS2W(X, Y: Integer; var WX, WY: Extended): Boolean;
  1966. begin
  1967.   Result := True;
  1968.   X := X - FRPlot.Left;
  1969.   Y := FRPlot.Bottom-1 - Y;
  1970.   WX := FXAxis.Min + X / Xqnt;
  1971.   WY := FYAxis.Min + Y / Yqnt;
  1972.   if WX < FXAxis.Min then Result := False;
  1973.   if WX > FXAxis.Max then Result := False;
  1974.   if WY < FYAxis.Min then Result := False;
  1975.   if WY > FYAxis.Max then Result := False;
  1976. end;
  1977. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1978.  
  1979. procedure Tth2DGraph.Freeze(Value: Boolean);
  1980. begin
  1981.   if FFreeze = Value then Exit;
  1982.   FFreeze := Value;
  1983.   if not Value then begin
  1984.         FBorder.Canvas.CopyRect(FRPlot, FPlot.Canvas, FRPlot);
  1985.         Canvas.CopyRect(FRBorder, FBorder.Canvas, FRBorder);
  1986.       end;
  1987. end;
  1988. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1989.  
  1990. procedure Tth2DGraph.HideLayer(Layer: Integer);
  1991. begin
  1992.   if (Layer < 1) or (Layer > MAX_CURVES) then Exit;
  1993.   FDataLength[Layer] := 1;
  1994.   Redraw;
  1995. end;
  1996. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  1997.  
  1998. procedure Tth2DGraph.LayerOptions(Layer: Integer; PlotMode: TPlotMode; PenWidth: Integer);
  1999. begin
  2000.   if (Layer < 1) or (Layer > MAX_CURVES) then Exit;
  2001.   FLayerOptions := True;
  2002.   FLayerOpt[Layer].PlotMode := Plotmode;
  2003.   FLayerOpt[Layer].PenWidth := PenWidth;
  2004. end;
  2005. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  2006.  
  2007. procedure Tth2DGraph.Paint;
  2008. begin
  2009.   if XAxis.Orientation <> orHorizontal then XAxis.Orientation := orHorizontal;
  2010.   if YAxis.Orientation <> orVertical   then YAxis.Orientation := orVertical;
  2011.   inherited Paint;
  2012.   Redraw;
  2013. end;
  2014. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  2015.  
  2016. procedure Tth2DGraph.UnHideLayer(Layer: Integer);
  2017. begin
  2018.   if (Layer < 1) or (Layer > MAX_CURVES) then Exit;
  2019.   FDataLength[Layer] := Length(FDataArray[Layer]);
  2020.   Redraw;
  2021. end;
  2022. {MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW}
  2023.  
  2024. end.
  2025.  
  2026.  
  2027.  
  2028.  
  2029.  
  2030.