home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d12345 / CHEMPLOT.ZIP / TPlot / DBPlot.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-01  |  31KB  |  926 lines

  1. unit DBPlot;
  2.  
  3. {$I Plot.inc}
  4.  
  5. {-----------------------------------------------------------------------------
  6. The contents of this file are subject to the Q Public License
  7. ("QPL"); you may not use this file except in compliance
  8. with the QPL. You may obtain a copy of the QPL from 
  9. the file QPL.html in this distribution, derived from:
  10.  
  11. http://www.trolltech.com/products/download/freelicense/license.html
  12.  
  13. The QPL prohibits development of proprietary software. 
  14. There is a Professional Version of this software available for this. 
  15. Contact sales@chemware.hypermart.net for more information.
  16.  
  17. Software distributed under the QPL is distributed on an "AS IS" basis,
  18. WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the QPL for
  19. the specific language governing rights and limitations under the QPL.
  20.  
  21. The Original Code is: pSeries.pas, released 12 September 2000.
  22.  
  23. The Initial Developer of the Original Code is Mat Ballard.
  24. Portions created by Mat Ballard are Copyright (C) 1999 Mat Ballard.
  25. Portions created by Microsoft are Copyright (C) 1998, 1999 Microsoft Corp.
  26. All Rights Reserved.
  27.  
  28. Contributor(s): Mat Ballard                 e-mail: mat.ballard@chemware.hypermart.net.
  29.  
  30. Last Modified: 02/25/2000
  31. Current Version: 2.00
  32.  
  33. You may retrieve the latest version of this file from:
  34.  
  35.         http://Chemware.hypermart.net/
  36.  
  37. This work was created with the Project JEDI VCL guidelines:
  38.  
  39.         http://www.delphi-jedi.org/Jedi:VCLVCL
  40.  
  41. in mind. 
  42.  
  43. Purpose:
  44. This unit contains the TDBPlot component - the data-aware version of the
  45. TPlot component
  46.  
  47. Known Issues:
  48.  
  49. History:
  50.  
  51.  
  52.  
  53. -----------------------------------------------------------------------------}
  54.  
  55. interface
  56.  
  57. uses
  58.   Classes, DB, SysUtils,
  59. {$IFDEF WINDOWS}
  60.   WinTypes, WinProcs,
  61.   DBCtrls, DBTables,
  62.   //Clipbrd, Controls, Dialogs, Extctrls, Forms, Graphics, Menus, Printers, Stdctrls,
  63. {$ENDIF}
  64. {$IFDEF WIN32}
  65.   Windows,
  66.   DBCtrls, DBTables,
  67.   //Clipbrd, Controls, Dialogs, Extctrls, Forms, Graphics, Menus, Printers, Stdctrls,
  68. {$ENDIF}
  69. {$IFDEF LINUX}
  70.   Types, Untranslated,
  71.   DBClient,
  72.   QDBCtrls,
  73.   //QClipbrd, QControls, QDialogs, QExtctrls, QForms, QGraphics,
  74.   //QImgList, QMenus, QStdctrls,
  75. {$ENDIF}
  76.  
  77.   Misc, Plot, PlotDefs, Data;
  78.  
  79. type
  80.   TCustomDBPlot = class(TCustomPlot)
  81.   private
  82.     FDataLink: TFieldDataLink;
  83. {Comment: I've studied TDBEdit, and am thoroughly confused by the co-existence of:
  84.     FReadOnly and
  85.     inherited ReadOnly from TCustomEdit
  86. from what I understand, I think that TDBPlot only needs a ReadOnly property that
  87. derives from FDataLink.}
  88.     {FReadOnly: Boolean;}
  89.     FUpdating: Boolean;
  90.  
  91.     function GetDataField: string;
  92.     function GetDataSource: TDataSource;
  93.     function GetReadOnly: Boolean;
  94.     procedure SetDataField(const Value: string);
  95.     procedure SetDataSource(Value: TDataSource);
  96.     procedure SetReadOnly(Value: Boolean);
  97.   protected
  98.     procedure SetNoSeries(Value: Word); override;
  99.  
  100.     property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
  101. {Is the database read-only ?}
  102.     property DataField: string read GetDataField write SetDataField;
  103. {The usual DataField property, which is the FieldName property of the DataLink.}
  104.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  105. {The usual DataSource property, which is the DataSource property of the DataLink.}
  106.  
  107.     procedure LoadFromDB;
  108.     procedure StoreInDB;
  109.  
  110.     procedure DataChange(Sender: TObject);
  111.     procedure DoDataChange(Sender: TObject); override;
  112.     procedure EditingChange(Sender: TObject);
  113.     procedure UpdateData(Sender: TObject);
  114.  
  115.   public
  116.     constructor Create(AOwner: TComponent); override;
  117. {The standard DB constructor, in which the DataLink is created.}
  118.     destructor Destroy; override;
  119. {The standard DB destructor, in which the DataLink is freed.}
  120.  
  121.     procedure Clear(Cancellable: Boolean); override;
  122. {Saves any changed files (at user request) and then clears the SeriesList.}
  123.  
  124. {Series manipulation:}
  125.     function AddSeries(XSeriesIndex: Integer): Integer; override;
  126. {If permitted, this adds a new, empty series to the list by calling its ancestor.}
  127.     function AddExternalSeries(XPointer, YPointer: pSingleArray;
  128.       NumberOfPoints: Integer): Integer; override;
  129. {If permitted, this adds a new, empty series to the list by calling its ancestor,
  130.  and sets its data to point to the external XPointer, YPointer data.}
  131.     function AddInternalSeries(XPointer, YPointer: pSingleArray;
  132.       NumberOfPoints: Integer): Integer; override;
  133. {If permitted, this adds a new, empty series to the list by calling its ancestor,
  134.  and copies the data from the XPointer, YPointer data.}
  135.     function CloneSeries(TheSeries: Integer): Integer; override;
  136. {If permitted, this adds a new, empty series to the list by calling its ancestor,
  137.  copies the data and properties from TheSeries into the new clone, and changes the color and Y Displacement.}
  138.     procedure DeleteSeries(Index: Integer); override;
  139. {If permitted, this deletes TheSeries from the list by calling its ancestor.}
  140.  
  141. {Manipulation of data IN the series:}
  142.     function AddDrawPoint(iSeries: Integer; X, Y: Single): Integer; 
  143. {If permitted, this calls TSeries.AddDrawPoint.}
  144.     function AddPoint(iSeries: Integer; X, Y: Single; FireEvent, AdjustAxes: Boolean): Integer; 
  145. {If permitted, this calls TSeries.AddPoint.}
  146.     function AddStringPoint(iSeries: Integer; XString: String; X, Y: Single; FireEvent, AdjustAxes: Boolean): Integer; 
  147. {If permitted, this calls TSeries.AddStringPoint.}
  148.     function InsertPoint(iSeries: Integer; X, Y: Single): Integer; 
  149. {If permitted, this calls TSeries.InsertPoint.}
  150.     procedure ReplacePoint(iSeries: Integer; N: Integer; NewX, NewY: Single); 
  151. {If permitted, this calls TSeries.ReplacePoint.}
  152.     procedure Compress(iSeries: Integer; CompressRatio: Integer);
  153. {If permitted, this calls TSeries.Compress.}
  154.     procedure Contract(iSeries: Integer; TheStart, TheFinish: Integer);
  155. {If permitted, this calls TSeries.Contract.}
  156.     function DelPoint(iSeries: Integer; X, Y: Single; Confirm: Boolean): Integer;
  157. {If permitted, this calls TSeries.DelPoint.}
  158.     function DelPointNumber(iSeries: Integer; ThePoint: Integer; Confirm: Boolean): Integer;
  159. {If permitted, this calls TSeries.DelPointNumber.}
  160.     function DelData(iSeries: Integer): Boolean;
  161. {If permitted, this calls TSeries.DelData.}
  162.     procedure Smooth(iSeries: Integer; SmoothOrder: Integer);
  163. {If permitted, this calls TSeries.Smooth.}
  164.     procedure Sort(iSeries: Integer);
  165. {If permitted, this calls TSeries.Sort.}
  166.     procedure Differentiate(iSeries: Integer);
  167. {If permitted, this calls TSeries.Differentiate.}
  168.     procedure Integrate(iSeries: Integer);
  169. {If permitted, this calls TSeries.Integrate.}
  170.     procedure MovingAverage(iSeries: Integer; Span: Integer);
  171. {If permitted, this calls TSeries.MovingAverage.}
  172.  
  173.     procedure UpdateRecord;
  174. {This causes the database to be updated.}
  175.   published
  176.  
  177.   end;
  178.  
  179.   TDBPlot = class(TCustomDBPlot)
  180.   protected
  181.  
  182.   public
  183.     Property AxisList;
  184. {This is a list of all the axes. The 0th is X, the 1st Y.}
  185.     Property Bitmap;
  186. {This returns a Bitmap of the Plot.}
  187.     Property PlotPopUpMenu;
  188. {The public exposure of the popupmenu for PlotMenu's use.}
  189.     Property Series;
  190. {This provided direct access to the series maintained by SeriesList.
  191.  DO NOT access any TSeries methods - just properties !}
  192.  
  193. {The following property remains protected and so hidden in the DataBase descendant:}
  194.     {Property SeriesList;}
  195. {This is the data in a list of data series.}
  196.     Property ScreenJob;
  197. {This is the job that is in progress in response to user input.}
  198.     Property ZAxis;
  199. {This is the Z Axis. Every nice 3D graph should have an Z Axis.}
  200. {}
  201. {This is fairly experimental at the moment, so use with caution.
  202.  It is also nil with non-3D PlotTypes.}
  203.  
  204.   published
  205.     property DataField;
  206. {The usual DataField property, which is the FieldName property of the DataLink.}
  207.     property DataSource;
  208. {The usual DataSource property, which is the DataSource property of the DataLink.}
  209.     property ReadOnly;
  210. {Is the database read-only ?}
  211.  
  212. {All the protected properties of TCustomPlot:}
  213.     Property About;
  214. {Displays the "About" dialog box for this component.}
  215.     Property AxesProperties;
  216. {Displays the "Axis Editor" dialog box for the FAxisList subcomponent.}
  217.     {Property DataProperties;}
  218. {Displays the "Data Editor" dialog box.}
  219.     {Property SeriesProperties;}
  220. {Displays the "Series Editor" dialog box.}
  221.     Property Border;
  222. {Manages the geometry of TCustomPlot: where the axes are, where they can go, etc.}
  223.     Property ClickAndDragDelay;
  224. {The delay (in milliseconds) before a clicked object becomes draggable.}
  225.     Property ColumnGap;
  226. {This is the percentage gap between groups of Columns in ptColumn PlotType.}
  227.     Property ContourDetail;
  228. {This is the detail of the colour interpolation in a contour graph.
  229.      cdLow: each triangular tile has uniform colour; this is pretty grainy
  230.      cdMedium: each pixel in each triangular tile has its own colour: this makes a good bitmap, but a lousy metafile
  231.      cdHigh: each rectangular pixel in each triangular tile has its own colour: this makes a good metafile
  232.  See SeriesList.DrawContour.}
  233.  
  234. {$IFNDEF DELPHI1}
  235.     Property CreatedBy;
  236. {For a metafile, this is a string that is stored in the metafile.}
  237.     Property Description;
  238. {For a metafile, this is a string that is stored in the metafile.}
  239. {$ENDIF}
  240.  
  241.     Property DisplayHistory;
  242. {The width of the X Axis when in History mode.}
  243.     Property DisplayMode;
  244. {See TDisplayMode.}
  245.     Property DefaultExtension;
  246. {What is the default extension of Plot files ?}
  247.     Property Editable;
  248. {Are screen objects like axes Editable ?}
  249.     Property FileName;
  250. {This is the filename to which the data is saved, or opened from.}
  251. {}
  252. {If FileName is blank, and an OpenClick or SaveClick occurs, then the standard
  253.  file dialog box appears to let the user pick a name.}
  254.     Property Grid;
  255. {Do we want a grid in XY-type plots ?}
  256.     Property GridStyle;
  257. {What pen style (dash, dot, etc) do we want for Grids ?}
  258.     property HighFont;
  259. {The font for annotation of the Highs and Lows.}
  260.  
  261. {$IFDEF COMPILER4_UP}
  262.     property Images;
  263. {A publication of the Popup Menu's Images property}
  264. {$ENDIF}
  265.  
  266.     Property HelpFile;
  267. {When this is set to "", TPlot uses Plot.hlp as its context-sensitive help file.}
  268. {}
  269. {When set to some other file, it uses that instead.}
  270.  
  271.     Property Instructions;
  272. {This is a hint-like message at the bottom of the graph.
  273.  It used to be Caption - a string - but now has to be a
  274.  stringlist to be fully Delphi-compatible (to avoid API calls).
  275.  Remember Kylix !
  276.  It disappears upon a MouseDown. See Font.}
  277.  
  278.     property Legend;
  279. {The list of series with their line styles. This is a moveable, on-screen object.}
  280.     Property Movable;
  281. {Are screen objects like axes movable ?}
  282.     Property Multiplicity;
  283. {When the PlotType is ptMultiple, the series are grouped into multiples of Multiplicity.
  284.  Otherwise ignored.}
  285.     property MultiplePen;
  286. {The pen to use for the verticle lines of ptMultiple PlotTypes (eg: High-Low).}
  287.     property MultiJoin;
  288. {Which two series, by number, to join with one rectangular symbol, in a ptMultiple plot.
  289.  Eg: if Multiplicity is 4, and MultiJoin = '2,3', then you have a "Candle" or
  290.  High-Low-Open-Close plot.}    
  291.     property PieRowCount;
  292. {The number of rows of Pie Graphs.}
  293.     property NoSeries;
  294. {The number of Series.}
  295.     property NoYAxes;
  296. {The total number of Y Axes (primary, secondary, tertiary, etc).}
  297.     Property OutlineWidth;
  298. {This is the width of the outline for screen objects like lines: axes and borders.}
  299.     Property PlotType;
  300. {What type of plot is this ?}
  301.     Property PolarRange;
  302. {What does 360░ correspond to in a polar graph ? Examples are:
  303.     2 Pi (6.28...),
  304.     360 (degrees),
  305.     60 (minutes),
  306.     24 (hours)
  307.     100 (%)
  308. Get the idea ?    }
  309.     Property PopupOptions;
  310. {If true, then these popup menu items are visible.}
  311.     Property PrintOrientation;
  312. {Shall we print the graph in Landscape or Portrait mode ?}
  313.     Property SaveOptions;
  314. {Shall we save the data as Text or binary ?}
  315. {}
  316. {Shall we also save the Plot properties when we save the data ?
  317.  If we do, then we:
  318.     1. Save the properties in a seperate file;
  319.     2. Look for a properties file to open.}
  320.     Property Title;
  321. {The title of the graph, including its geometry, font and visibility.}
  322.     Property XAxis;
  323. {This is the X Axis. Every nice graph should have an X Axis.}
  324.     Property YAxis;
  325. {This is the Y Axis. Every nice graph should have at least one Y Axis.}
  326. {}
  327. {Each Series must know what Y Axes it is being plotted against:
  328.  Primary (this one) or Secondary.}
  329.     Property ZAngle;
  330. {The angle made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  331.     Property ZLink;
  332. {Should we link 3D series together ?}
  333.  
  334. {Events:}
  335.     Property OnAfterPaint;
  336.     Property OnAfterDraw;
  337.     Property OnBeforePaint;
  338.     Property OnBeforeDraw;
  339.     Property OnStyleChange;
  340.     Property OnDataChange;
  341.  
  342.     Property OnFileOpen;
  343. {When a file is opened, the app can be notified of the new file name using this event.}
  344.  
  345.     Property OnFileClose;
  346. {When a file is closed, the app can be notified of the new file name using this event.}
  347.  
  348.     Property OnHeader;
  349. {When data is opened, this event passes the header information back to the "user".}
  350.  
  351.     Property OnHeaderRequest;
  352. {When data is saved or copied, this event allows the user to add a header
  353.  to the data.}
  354.  
  355.     Property OnHTMLHeaderRequest;
  356. {When data is copied as HTML, this event allows the user to add a header
  357.  to the data.}
  358.  
  359.     Property OnSelection;
  360.     Property OnDualSelection;
  361.  
  362. {all the "extra" TPanel properties in D4 (alias "VCL Bloat"):}
  363.  
  364. {Now all the TPanel properties-------------------------------------------------}
  365. {all the TPanel properties in D1:}
  366.     property Align;    
  367.     {property Alignment;}
  368.     property BevelInner;
  369.     property BevelOuter;
  370.     property BevelWidth;
  371.     property BorderWidth;
  372.     property BorderStyle;
  373.     {property Caption; - replaced by Instructions}
  374.     property Color;
  375. {$IFDEF MSWINDOWS}
  376.     property Ctl3D;
  377.     property DragCursor;
  378. {$ENDIF}
  379.     property DragMode;
  380.     property Enabled;
  381.     property Font;
  382. {This is the font of the hint-like message at the bottom of the graph.}
  383.     property ParentColor;
  384. {$IFDEF MSWINDOWS}
  385.     property Locked;
  386.     property ParentCtl3D;
  387. {$ENDIF}
  388.     property ParentFont;
  389.     property ParentShowHint;
  390. { Note: D1 to D4 were quite happy for:
  391.         PopupMenu := FPlotPopUpMenu;
  392.   FPlotPopUpMenu was then run by inherited MouseUp.
  393.   However, D5 introduced TControl.WMContextMenu, which ran BEFORE MouseDown.
  394.   This went spastic when it tried to Popup the PopupMenu.
  395.  
  396.   We have therefore returned to hiding FPlotPopUpMenu, and running it manually.
  397.     property PopupMenu;}
  398.     property ShowHint;
  399.     property TabOrder;
  400.     property TabStop;
  401.     property Visible;
  402.     property OnClick;
  403.     property OnDblClick;
  404.     property OnDragDrop;
  405.     property OnDragOver;
  406.     property OnEndDrag;
  407.     property OnEnter;
  408.     property OnExit;
  409.     property OnMouseDown;
  410.     property OnMouseMove;
  411.     property OnMouseUp;
  412.     property OnResize;
  413.  
  414.     
  415. {$IFDEF COMPILER2_UP}
  416. {$ENDIF}
  417.  
  418. {$IFDEF COMPILER3_UP}
  419.   {$IFDEF MSWINDOWS}
  420.     property FullRepaint;
  421.     property OnStartDrag;
  422.   {$ENDIF}
  423. {$ENDIF}
  424.  
  425. {$IFDEF COMPILER4_UP}
  426.     property Anchors;
  427.     // property AutoSize; - leads to bizzare behaviour
  428.   {$IFDEF MSWINDOWS}
  429.     property BiDiMode;
  430.   {$ENDIF}
  431.     property Constraints;
  432.   {$IFDEF MSWINDOWS}
  433.     property UseDockManager default True;
  434.     property DockSite;
  435.     property DragKind;
  436.     property ParentBiDiMode;
  437.     property OnCanResize;
  438.   {$ENDIF}
  439.     property OnConstrainedResize;
  440.   {$IFDEF MSWINDOWS}
  441.     property OnDockDrop;
  442.     property OnDockOver;
  443.     property OnEndDock;
  444.     property OnGetSiteInfo;
  445.     property OnStartDock;
  446.     property OnUnDock;
  447.   {$ENDIF}
  448. {$ENDIF}
  449.  
  450. {$IFDEF COMPILER5_UP}
  451. {$ENDIF}
  452.   end;
  453.  
  454. implementation
  455.  
  456. {------------------------------------------------------------------------------
  457.   Constructor: DBPlot.Create
  458.   Description: standard DB constructor
  459.        Author: Mat Ballard
  460.  Date created: 03/02/2001
  461. Date modified: 03/02/2001 by Mat Ballard
  462.       Purpose:
  463.  Known Issues:
  464.  ------------------------------------------------------------------------------}
  465. constructor TCustomDBPlot.Create(AOwner: TComponent);
  466. begin
  467.   inherited Create(AOwner);
  468.   {FReadOnly := FALSE;}
  469.   FDataLink := TFieldDataLink.Create;
  470.   FDataLink.Control := Self;
  471.   FDataLink.OnDataChange := DataChange;
  472.   FDataLink.OnEditingChange := EditingChange;
  473.   FDataLink.OnUpdateData := UpdateData;
  474.   //FDataLink.OnActiveChange := ActiveChange;
  475. end;
  476.  
  477. {------------------------------------------------------------------------------
  478.    Destructor: DBPlot.Destroy
  479.   Description: standard DB destructor
  480.        Author: Mat Ballard
  481.  Date created: 03/07/2001
  482. Date modified: 03/07/2001 by Mat Ballard
  483.       Purpose: frees the datalink
  484.  Known Issues:
  485.  ------------------------------------------------------------------------------}
  486. destructor TCustomDBPlot.Destroy;
  487. begin
  488.   FDataLink.OnDataChange := nil;
  489.   FDataLink.Free;
  490.   inherited Destroy;
  491. end;
  492.  
  493. {------------------------------------------------------------------------------
  494.     Procedure: TCustomDBPlot.Clear
  495.   Description: Clears the SeriesList.
  496.        Author: Mat Ballard
  497.  Date created: 05/02/2001
  498. Date modified: 05/02/2001 by Mat Ballard
  499.       Purpose: Series management: wraps TSeriesList.ClearSeries
  500.  Known Issues: it is a fairly brutal way of setting the number of Y Axes
  501.  ------------------------------------------------------------------------------}
  502. procedure TCustomDBPlot.Clear(Cancellable: Boolean);
  503. begin
  504.   if ((not FUpdating) and ReadOnly) then exit;
  505.  
  506.   inherited Clear(Cancellable);
  507. end;
  508.  
  509. {------------------------------------------------------------------------------
  510.     Procedure: TCustomDBPlot.DataChange
  511.   Description: handles changes in the source DB data
  512.        Author: Mat Ballard
  513.  Date created: 03/07/2001
  514. Date modified: 03/07/2001 by Mat Ballard
  515.       Purpose: loads the data from the database
  516.  Known Issues:
  517.  ------------------------------------------------------------------------------}
  518. procedure TCustomDBPlot.DataChange(Sender: TObject);
  519. begin
  520. {blow away the old data:}
  521.   Self.SeriesList.ClearSeries;
  522. {no new data ? POQ:}
  523.   if FDataLink.Field = nil then exit;
  524.  
  525. {now the work of loading the data from the DB begins.}
  526.   LoadFromDB;
  527. end;
  528.  
  529. procedure TCustomDBPlot.DoDataChange(Sender: TObject);
  530. begin
  531.   FDataLink.Edit;
  532.   FDataLink.Modified;
  533.   inherited DoDataChange(Sender);
  534. end;
  535.  
  536. procedure TCustomDBPlot.EditingChange(Sender: TObject);
  537. begin
  538.   ReadOnly := not FDataLink.Editing;
  539. end;
  540.  
  541. {------------------------------------------------------------------------------
  542.     Procedure: TCustomDBPlot.UpdateData
  543.   Description: handles changes in the Plot data
  544.        Author: Mat Ballard
  545.  Date created: 03/07/2001
  546. Date modified: 03/07/2001 by Mat Ballard
  547.       Purpose: stores the data in the database
  548.  Known Issues:
  549.  ------------------------------------------------------------------------------}
  550. procedure TCustomDBPlot.UpdateData(Sender: TObject);
  551. begin
  552. {no new data ? POQ:}
  553.   if FDataLink.Field = nil then exit;
  554. {now the work of loading the data from the DB begins.}
  555.   if FDataLink.CanModify then
  556.     StoreInDB;
  557. end;
  558.  
  559. function TCustomDBPlot.GetDataField: string;
  560. begin
  561.   Result := FDataLink.FieldName;
  562. end;
  563.  
  564. procedure TCustomDBPlot.SetDataField(const Value: string);
  565. begin
  566.   {if not (csDesigning in ComponentState) then
  567.     ResetMaxLength;}
  568.   FDataLink.FieldName := Value;
  569. end;
  570.  
  571. function TCustomDBPlot.GetDataSource: TDataSource;
  572. begin
  573.   Result := FDataLink.DataSource;
  574. end;
  575.  
  576. procedure TCustomDBPlot.SetDataSource(Value: TDataSource);
  577. begin
  578.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  579.     FDataLink.DataSource := Value;
  580.   if Value <> nil then Value.FreeNotification(Self);
  581. end;
  582.  
  583. function TCustomDBPlot.GetReadOnly: Boolean;
  584. begin
  585.   Result := FDataLink.ReadOnly;
  586. end;
  587.  
  588. procedure TCustomDBPlot.SetReadOnly(Value: Boolean);
  589. begin
  590.   FDataLink.ReadOnly := Value;
  591. end;
  592.  
  593. {------------------------------------------------------------------------------
  594.      Function: TCustomDBPlot.SetNoSeries
  595.   Description:
  596.        Author: Mat Ballard
  597.  Date created: 05/29/2001
  598. Date modified: 05/29/2001 by Mat Ballard
  599.       Purpose: Sets the number of series by adding or subtracting series, if permitted.
  600.  Return Value: the Index of the new Series
  601.  Known Issues:
  602.  ------------------------------------------------------------------------------}
  603. procedure TCustomDBPlot.SetNoSeries(Value: Word); 
  604. begin
  605.   if ((not FUpdating) and ReadOnly) then
  606.     EComponentError.Create('The data is ReadOnly !' + #13+#10 +
  607.       'I cannot change the number of Series !')
  608.   else
  609.   begin
  610.     inherited SetNoSeries(Value);
  611.   end;
  612. end;
  613.  
  614. {------------------------------------------------------------------------------
  615.      Function: TCustomDBPlot.Add
  616.   Description:
  617.        Author: Mat Ballard
  618.  Date created: 03/02/2001
  619. Date modified: 03/02/2001 by Mat Ballard
  620.       Purpose: Adds a new, empty data Series to the graph
  621.  Return Value: the Index of the new Series
  622.  Known Issues:
  623.  ------------------------------------------------------------------------------}
  624. function TCustomDBPlot.AddSeries(XSeriesIndex: Integer): Integer;
  625. begin
  626.   if ((not FUpdating) and ReadOnly) then
  627.     Result := -1
  628.   else
  629.   begin
  630.     Result := inherited AddSeries(XSeriesIndex);
  631.   end;
  632. end;
  633.  
  634. {------------------------------------------------------------------------------
  635.      Function: TCustomDBPlot.AddExternal
  636.   Description: wrapper for TSeriesList.AddExternal
  637.        Author: Mat Ballard
  638.  Date created: 03/02/2001
  639. Date modified: 03/02/2001 by Mat Ballard
  640.       Purpose: Adds a new data Series that is maintained elsewhere to the graph
  641.  Known Issues:
  642.  ------------------------------------------------------------------------------}
  643. function TCustomDBPlot.AddExternalSeries(
  644.   XPointer,
  645.   YPointer: pSingleArray;
  646.   NumberOfPoints: Integer): Integer;
  647. begin
  648.   if ((not FUpdating) and ReadOnly) then
  649.     Result := -1
  650.   else
  651.   begin
  652.     Result := inherited AddExternalSeries(XPointer, YPointer, NumberOfPoints);
  653.   end;
  654. end;
  655.  
  656. {------------------------------------------------------------------------------
  657.      Function: TCustomDBPlot.AddInternal
  658.   Description: wrapper for TSeriesList.AddInternal
  659.        Author: Mat Ballard
  660.  Date created: 03/02/2001
  661. Date modified: 03/02/2001 by Mat Ballard
  662.       Purpose: Adds a new data Series from elsewhere to the graph, and saves it internally
  663.  Known Issues:
  664.  ------------------------------------------------------------------------------}
  665. function TCustomDBPlot.AddInternalSeries(
  666.   XPointer,
  667.   YPointer: pSingleArray;
  668.   NumberOfPoints: Integer): Integer;
  669. begin
  670.   if ((not FUpdating) and ReadOnly) then
  671.     Result := -1
  672.   else
  673.   begin
  674.     Result := inherited AddInternalSeries(XPointer, YPointer, NumberOfPoints);
  675.   end;
  676. end;
  677.  
  678. {------------------------------------------------------------------------------
  679.     Procedure: TCustomDBPlot.CloneSeries
  680.   Description: wrapper for TSeriesList.CloneSeries
  681.        Author: Mat Ballard
  682.  Date created: 03/02/2001
  683. Date modified: 03/02/2001 by Mat Ballard
  684.       Purpose: Clones the specified Series
  685.  Known Issues:
  686.  ------------------------------------------------------------------------------}
  687. function TCustomDBPlot.CloneSeries(TheSeries: Integer): Integer;
  688. begin
  689.   if ((not FUpdating) and ReadOnly) then
  690.     Result := -1
  691.   else
  692.   begin
  693.     Result := inherited CloneSeries(TheSeries);
  694.   end;
  695. end;
  696.  
  697. {------------------------------------------------------------------------------
  698.     Procedure: TCustomDBPlot.DeleteSeries
  699.   Description: wrapper for TSeriesList.DeleteSeries
  700.        Author: Mat Ballard
  701.  Date created: 03/02/2001
  702. Date modified: 03/02/2001 by Mat Ballard
  703.       Purpose: Deletes the specified Series
  704.  Known Issues:
  705.  ------------------------------------------------------------------------------}
  706. procedure TCustomDBPlot.DeleteSeries(Index: Integer);
  707. begin
  708.   if ((not FUpdating) and ReadOnly) then exit;
  709.  
  710.   inherited DeleteSeries(Index);
  711. end;
  712.  
  713. function TCustomDBPlot.AddDrawPoint(iSeries: Integer; X, Y: Single): Integer;
  714. begin
  715.   if ((not FUpdating) and ReadOnly) then
  716.     Result := -1
  717.   else
  718.   begin
  719.     Result := TSeries(FSeriesList.Items[iSeries]).AddDrawPoint(X, Y, Self.Canvas);
  720.   end;
  721. end;
  722.  
  723. function TCustomDBPlot.AddPoint(iSeries: Integer; X, Y: Single; FireEvent, AdjustAxes: Boolean): Integer;
  724. begin
  725.   if ((not FUpdating) and ReadOnly) then
  726.     Result := -1
  727.   else
  728.   begin
  729.     Result := TSeries(FSeriesList.Items[iSeries]).AddPoint(X, Y, FireEvent, AdjustAxes);
  730.   end;
  731. end;
  732.  
  733. function TCustomDBPlot.AddStringPoint(iSeries: Integer; XString: String; X, Y: Single; FireEvent, AdjustAxes: Boolean): Integer;
  734. begin
  735.   if ((not FUpdating) and ReadOnly) then
  736.     Result := -1
  737.   else
  738.   begin
  739.     Result := TSeries(FSeriesList.Items[iSeries]).AddStringPoint(XString, X, Y, FireEvent, AdjustAxes);
  740.   end;
  741. end;
  742.  
  743. function TCustomDBPlot.InsertPoint(iSeries: Integer; X, Y: Single): Integer;
  744. begin
  745.   if ((not FUpdating) and ReadOnly) then
  746.     Result := -1
  747.   else
  748.   begin
  749.     Result := TSeries(FSeriesList.Items[iSeries]).InsertPoint(X, Y);
  750.   end;
  751. end;
  752.  
  753. procedure TCustomDBPlot.ReplacePoint(iSeries, N: Integer; NewX, NewY: Single);
  754. begin
  755.   if ((not FUpdating) and ReadOnly) then exit;
  756.  
  757.   TSeries(FSeriesList.Items[iSeries]).ReplacePoint(N, NewX, NewY);
  758. end;
  759.  
  760. procedure TCustomDBPlot.Compress(iSeries: Integer; CompressRatio: Integer);
  761. begin
  762.   if ((not FUpdating) and ReadOnly) then exit;
  763.  
  764.   TSeries(FSeriesList.Items[iSeries]).Compress(CompressRatio);
  765. end;
  766.  
  767. procedure TCustomDBPlot.Contract(iSeries: Integer; TheStart, TheFinish: Integer);
  768. begin
  769.   if ((not FUpdating) and ReadOnly) then exit;
  770.  
  771.   TSeries(FSeriesList.Items[iSeries]).Contract(TheStart, TheFinish);
  772. end;
  773.  
  774. function TCustomDBPlot.DelPoint(iSeries: Integer; X, Y: Single; Confirm: Boolean): Integer;
  775. begin
  776.   if ((not FUpdating) and ReadOnly) then
  777.     Result := -1
  778.   else
  779.   begin
  780.     Result := TSeries(FSeriesList.Items[iSeries]).DelPoint(X, Y, Confirm);
  781.   end;
  782. end;
  783.  
  784. function TCustomDBPlot.DelPointNumber(iSeries: Integer; ThePoint: Integer; Confirm: Boolean): Integer;
  785. begin
  786.   if ((not FUpdating) and ReadOnly) then
  787.     Result := -1
  788.   else
  789.   begin
  790.     Result := TSeries(FSeriesList.Items[iSeries]).DelPointNumber(ThePoint, Confirm);
  791.   end;
  792. end;
  793.  
  794. function TCustomDBPlot.DelData(iSeries: Integer): Boolean;
  795. begin
  796.   if ((not FUpdating) and ReadOnly) then
  797.     Result := FALSE
  798.   else
  799.   begin
  800.     Result := TSeries(FSeriesList.Items[iSeries]).DelData;
  801.   end;
  802. end;
  803.  
  804. procedure TCustomDBPlot.Smooth(iSeries: Integer; SmoothOrder: Integer);
  805. begin
  806.   if ((not FUpdating) and ReadOnly) then exit;
  807.  
  808.   TSeries(FSeriesList.Items[iSeries]).Smooth(SmoothOrder);
  809. end;
  810.  
  811. procedure TCustomDBPlot.Sort(iSeries: Integer);
  812. begin
  813.   if ((not FUpdating) and ReadOnly) then exit;
  814.  
  815.   TSeries(FSeriesList.Items[iSeries]).Sort;
  816. end;
  817.  
  818. procedure TCustomDBPlot.Differentiate(iSeries: Integer);
  819. begin
  820.   if ((not FUpdating) and ReadOnly) then exit;
  821.  
  822.   TSeries(FSeriesList.Items[iSeries]).Differentiate;
  823. end;
  824.  
  825. procedure TCustomDBPlot.Integrate(iSeries: Integer);
  826. begin
  827.   if ((not FUpdating) and ReadOnly) then exit;
  828.  
  829.   TSeries(FSeriesList.Items[iSeries]).Integrate;
  830. end;
  831.  
  832. procedure TCustomDBPlot.MovingAverage(iSeries: Integer; Span: Integer);
  833. begin
  834.   if ((not FUpdating) and ReadOnly) then exit;
  835.  
  836.   TSeries(FSeriesList.Items[iSeries]).MovingAverage(Span);
  837. end;
  838.  
  839. {------------------------------------------------------------------------------
  840.     Procedure: TCustomDBPlot.StoreInDB
  841.   Description: Stores the current plot data in a database
  842.        Author: Mat Ballard
  843.  Date created: 03/02/2001
  844. Date modified: 03/02/2001 by Mat Ballard
  845.       Purpose: database management
  846.  Known Issues:
  847.      Comments: based on a post from: "Bruce Roberts" <ber@attcanada.xnet> on
  848.                Dynamic arrays in databases, Sun Feb 25 2001.
  849.  ------------------------------------------------------------------------------}
  850. procedure TCustomDBPlot.StoreInDB;
  851. var
  852. {$IFDEF MSWINDOWS}
  853.   TheBlobStream: TBlobStream;
  854. {$ENDIF}
  855. {$IFDEF LINUX}
  856.   TheBlobStream: TClientBlobStream;
  857. {$ENDIF}
  858. begin
  859.   if (Self.DataSource.DataSet.CanModify) then
  860.   begin
  861. {$IFDEF MSWINDOWS}
  862.     TheBlobStream := TBlobStream.Create (TBlobField(FDataLink.Field), bmWrite);
  863. {$ENDIF}
  864. {$IFDEF LINUX}
  865.     TheBlobStream := TClientBlobStream.Create (TBlobField(FDataLink.Field), bmWrite);
  866. {$ENDIF}
  867.     try
  868.       Self.SaveToStream(TMemoryStream(TheBlobStream));
  869.     finally
  870.       TheBlobStream.Free;
  871.     end;
  872.   end;
  873. end;
  874.  
  875.  
  876. {------------------------------------------------------------------------------
  877.     Procedure: TCustomDBPlot.LoadFromDB
  878.   Description: loads fresh plot data from a database
  879.        Author: Mat Ballard
  880.  Date created: 03/02/2001
  881. Date modified: 03/02/2001 by Mat Ballard
  882.       Purpose: database management
  883.  Known Issues: we need to create a memorystream because Misc.Readline barfs
  884.                because GetLineLengthFromStream barfs.
  885.      Comments: based on a post from: "Bruce Roberts" <ber@attcanada.xnet> on
  886.                Dynamic arrays in databases, Sun Feb 25 2001.
  887.  ------------------------------------------------------------------------------}
  888. procedure TCustomDBPlot.LoadFromDB;
  889. var
  890. {$IFDEF MSWINDOWS}
  891.   TheBlobStream: TBlobStream;
  892. {$ENDIF}
  893. {$IFDEF LINUX}
  894.   TheBlobStream: TStream;
  895. {$ENDIF}
  896.   TheMemoryStream: TMemoryStream;
  897. begin
  898.   Self.FSeriesList.ClearSeries;
  899. {$IFDEF MSWINDOWS}
  900.   TheBlobStream := TBlobStream.Create (TBlobField(FDataLink.Field), bmRead);
  901. {$ENDIF}
  902. {$IFDEF LINUX}
  903.   TheBlobStream :=
  904.     Self.FDataLink.DataSet.CreateBlobStream(TBlobField(FDataLink.Field), bmRead);
  905. {$ENDIF}
  906.   TheMemoryStream := TMemoryStream.Create;
  907.   try
  908.     if (TheBlobStream.Size > 20) then
  909.     begin
  910.       TheMemoryStream.LoadFromStream(TheBlobStream);
  911.       TheMemoryStream.Seek(0, soFromBeginning);
  912.       Self.LoadFromStream(TheMemoryStream);
  913.     end
  914.   finally
  915.     TheBlobStream.Free;
  916.     TheMemoryStream.Free;
  917.   end;
  918. end;
  919.  
  920. procedure TCustomDBPlot.UpdateRecord;
  921. begin
  922.   FDatalink.UpdateRecord;
  923. end;
  924.  
  925. end.
  926.