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