home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kompon / d123456 / CHEMPLOT.ZIP / TPlot / DBPlot.pas < prev    next >
Pascal/Delphi Source File  |  2001-07-02  |  31KB  |  928 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. resourcestring
  457.   sSetNoSeries1 = 'The data is ReadOnly !' + #13+#10 +
  458.       'I cannot change the number of Series !';
  459. {------------------------------------------------------------------------------
  460.   Constructor: DBPlot.Create
  461.   Description: standard DB constructor
  462.        Author: Mat Ballard
  463.  Date created: 03/02/2001
  464. Date modified: 03/02/2001 by Mat Ballard
  465.       Purpose:
  466.  Known Issues:
  467.  ------------------------------------------------------------------------------}
  468. constructor TCustomDBPlot.Create(AOwner: TComponent);
  469. begin
  470.   inherited Create(AOwner);
  471.   {FReadOnly := FALSE;}
  472.   FDataLink := TFieldDataLink.Create;
  473.   FDataLink.Control := Self;
  474.   FDataLink.OnDataChange := DataChange;
  475.   FDataLink.OnEditingChange := EditingChange;
  476.   FDataLink.OnUpdateData := UpdateData;
  477.   //FDataLink.OnActiveChange := ActiveChange;
  478. end;
  479.  
  480. {------------------------------------------------------------------------------
  481.    Destructor: DBPlot.Destroy
  482.   Description: standard DB destructor
  483.        Author: Mat Ballard
  484.  Date created: 03/07/2001
  485. Date modified: 03/07/2001 by Mat Ballard
  486.       Purpose: frees the datalink
  487.  Known Issues:
  488.  ------------------------------------------------------------------------------}
  489. destructor TCustomDBPlot.Destroy;
  490. begin
  491.   FDataLink.OnDataChange := nil;
  492.   FDataLink.Free;
  493.   inherited Destroy;
  494. end;
  495.  
  496. {------------------------------------------------------------------------------
  497.     Procedure: TCustomDBPlot.Clear
  498.   Description: Clears the SeriesList.
  499.        Author: Mat Ballard
  500.  Date created: 05/02/2001
  501. Date modified: 05/02/2001 by Mat Ballard
  502.       Purpose: Series management: wraps TSeriesList.ClearSeries
  503.  Known Issues: it is a fairly brutal way of setting the number of Y Axes
  504.  ------------------------------------------------------------------------------}
  505. procedure TCustomDBPlot.Clear(Cancellable: Boolean);
  506. begin
  507.   if ((not FUpdating) and ReadOnly) then exit;
  508.  
  509.   inherited Clear(Cancellable);
  510. end;
  511.  
  512. {------------------------------------------------------------------------------
  513.     Procedure: TCustomDBPlot.DataChange
  514.   Description: handles changes in the source DB data
  515.        Author: Mat Ballard
  516.  Date created: 03/07/2001
  517. Date modified: 03/07/2001 by Mat Ballard
  518.       Purpose: loads the data from the database
  519.  Known Issues:
  520.  ------------------------------------------------------------------------------}
  521. procedure TCustomDBPlot.DataChange(Sender: TObject);
  522. begin
  523. {blow away the old data:}
  524.   Self.SeriesList.ClearSeries;
  525. {no new data ? POQ:}
  526.   if FDataLink.Field = nil then exit;
  527.  
  528. {now the work of loading the data from the DB begins.}
  529.   LoadFromDB;
  530. end;
  531.  
  532. procedure TCustomDBPlot.DoDataChange(Sender: TObject);
  533. begin
  534.   FDataLink.Edit;
  535.   FDataLink.Modified;
  536.   inherited DoDataChange(Sender);
  537. end;
  538.  
  539. procedure TCustomDBPlot.EditingChange(Sender: TObject);
  540. begin
  541.   ReadOnly := not FDataLink.Editing;
  542. end;
  543.  
  544. {------------------------------------------------------------------------------
  545.     Procedure: TCustomDBPlot.UpdateData
  546.   Description: handles changes in the Plot data
  547.        Author: Mat Ballard
  548.  Date created: 03/07/2001
  549. Date modified: 03/07/2001 by Mat Ballard
  550.       Purpose: stores the data in the database
  551.  Known Issues:
  552.  ------------------------------------------------------------------------------}
  553. procedure TCustomDBPlot.UpdateData(Sender: TObject);
  554. begin
  555. {no new data ? POQ:}
  556.   if FDataLink.Field = nil then exit;
  557. {now the work of loading the data from the DB begins.}
  558.   if FDataLink.CanModify then
  559.     StoreInDB;
  560. end;
  561.  
  562. function TCustomDBPlot.GetDataField: string;
  563. begin
  564.   Result := FDataLink.FieldName;
  565. end;
  566.  
  567. procedure TCustomDBPlot.SetDataField(const Value: string);
  568. begin
  569.   {if not (csDesigning in ComponentState) then
  570.     ResetMaxLength;}
  571.   FDataLink.FieldName := Value;
  572. end;
  573.  
  574. function TCustomDBPlot.GetDataSource: TDataSource;
  575. begin
  576.   Result := FDataLink.DataSource;
  577. end;
  578.  
  579. procedure TCustomDBPlot.SetDataSource(Value: TDataSource);
  580. begin
  581.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  582.     FDataLink.DataSource := Value;
  583.   if Value <> nil then Value.FreeNotification(Self);
  584. end;
  585.  
  586. function TCustomDBPlot.GetReadOnly: Boolean;
  587. begin
  588.   Result := FDataLink.ReadOnly;
  589. end;
  590.  
  591. procedure TCustomDBPlot.SetReadOnly(Value: Boolean);
  592. begin
  593.   FDataLink.ReadOnly := Value;
  594. end;
  595.  
  596. {------------------------------------------------------------------------------
  597.      Function: TCustomDBPlot.SetNoSeries
  598.   Description:
  599.        Author: Mat Ballard
  600.  Date created: 05/29/2001
  601. Date modified: 05/29/2001 by Mat Ballard
  602.       Purpose: Sets the number of series by adding or subtracting series, if permitted.
  603.  Return Value: the Index of the new Series
  604.  Known Issues:
  605.  ------------------------------------------------------------------------------}
  606. procedure TCustomDBPlot.SetNoSeries(Value: Word); 
  607. begin
  608.   if ((not FUpdating) and ReadOnly) then
  609.     EComponentError.Create(sSetNoSeries1)
  610.   else
  611.   begin
  612.     inherited SetNoSeries(Value);
  613.   end;
  614. end;
  615.  
  616. {------------------------------------------------------------------------------
  617.      Function: TCustomDBPlot.Add
  618.   Description:
  619.        Author: Mat Ballard
  620.  Date created: 03/02/2001
  621. Date modified: 03/02/2001 by Mat Ballard
  622.       Purpose: Adds a new, empty data Series to the graph
  623.  Return Value: the Index of the new Series
  624.  Known Issues:
  625.  ------------------------------------------------------------------------------}
  626. function TCustomDBPlot.AddSeries(XSeriesIndex: Integer): Integer;
  627. begin
  628.   if ((not FUpdating) and ReadOnly) then
  629.     Result := -1
  630.   else
  631.   begin
  632.     Result := inherited AddSeries(XSeriesIndex);
  633.   end;
  634. end;
  635.  
  636. {------------------------------------------------------------------------------
  637.      Function: TCustomDBPlot.AddExternal
  638.   Description: wrapper for TSeriesList.AddExternal
  639.        Author: Mat Ballard
  640.  Date created: 03/02/2001
  641. Date modified: 03/02/2001 by Mat Ballard
  642.       Purpose: Adds a new data Series that is maintained elsewhere to the graph
  643.  Known Issues:
  644.  ------------------------------------------------------------------------------}
  645. function TCustomDBPlot.AddExternalSeries(
  646.   XPointer,
  647.   YPointer: pSingleArray;
  648.   NumberOfPoints: Integer): Integer;
  649. begin
  650.   if ((not FUpdating) and ReadOnly) then
  651.     Result := -1
  652.   else
  653.   begin
  654.     Result := inherited AddExternalSeries(XPointer, YPointer, NumberOfPoints);
  655.   end;
  656. end;
  657.  
  658. {------------------------------------------------------------------------------
  659.      Function: TCustomDBPlot.AddInternal
  660.   Description: wrapper for TSeriesList.AddInternal
  661.        Author: Mat Ballard
  662.  Date created: 03/02/2001
  663. Date modified: 03/02/2001 by Mat Ballard
  664.       Purpose: Adds a new data Series from elsewhere to the graph, and saves it internally
  665.  Known Issues:
  666.  ------------------------------------------------------------------------------}
  667. function TCustomDBPlot.AddInternalSeries(
  668.   XPointer,
  669.   YPointer: pSingleArray;
  670.   NumberOfPoints: Integer): Integer;
  671. begin
  672.   if ((not FUpdating) and ReadOnly) then
  673.     Result := -1
  674.   else
  675.   begin
  676.     Result := inherited AddInternalSeries(XPointer, YPointer, NumberOfPoints);
  677.   end;
  678. end;
  679.  
  680. {------------------------------------------------------------------------------
  681.     Procedure: TCustomDBPlot.CloneSeries
  682.   Description: wrapper for TSeriesList.CloneSeries
  683.        Author: Mat Ballard
  684.  Date created: 03/02/2001
  685. Date modified: 03/02/2001 by Mat Ballard
  686.       Purpose: Clones the specified Series
  687.  Known Issues:
  688.  ------------------------------------------------------------------------------}
  689. function TCustomDBPlot.CloneSeries(TheSeries: Integer): Integer;
  690. begin
  691.   if ((not FUpdating) and ReadOnly) then
  692.     Result := -1
  693.   else
  694.   begin
  695.     Result := inherited CloneSeries(TheSeries);
  696.   end;
  697. end;
  698.  
  699. {------------------------------------------------------------------------------
  700.     Procedure: TCustomDBPlot.DeleteSeries
  701.   Description: wrapper for TSeriesList.DeleteSeries
  702.        Author: Mat Ballard
  703.  Date created: 03/02/2001
  704. Date modified: 03/02/2001 by Mat Ballard
  705.       Purpose: Deletes the specified Series
  706.  Known Issues:
  707.  ------------------------------------------------------------------------------}
  708. procedure TCustomDBPlot.DeleteSeries(Index: Integer);
  709. begin
  710.   if ((not FUpdating) and ReadOnly) then exit;
  711.  
  712.   inherited DeleteSeries(Index);
  713. end;
  714.  
  715. function TCustomDBPlot.AddDrawPoint(iSeries: Integer; X, Y: Single): Integer;
  716. begin
  717.   if ((not FUpdating) and ReadOnly) then
  718.     Result := -1
  719.   else
  720.   begin
  721.     Result := TSeries(FSeriesList.Items[iSeries]).AddDrawPoint(X, Y, Self.Canvas);
  722.   end;
  723. end;
  724.  
  725. function TCustomDBPlot.AddPoint(iSeries: Integer; X, Y: Single; FireEvent, AdjustAxes: Boolean): Integer;
  726. begin
  727.   if ((not FUpdating) and ReadOnly) then
  728.     Result := -1
  729.   else
  730.   begin
  731.     Result := TSeries(FSeriesList.Items[iSeries]).AddPoint(X, Y, FireEvent, AdjustAxes);
  732.   end;
  733. end;
  734.  
  735. function TCustomDBPlot.AddStringPoint(iSeries: Integer; XString: String; X, Y: Single; FireEvent, AdjustAxes: Boolean): Integer;
  736. begin
  737.   if ((not FUpdating) and ReadOnly) then
  738.     Result := -1
  739.   else
  740.   begin
  741.     Result := TSeries(FSeriesList.Items[iSeries]).AddStringPoint(XString, X, Y, FireEvent, AdjustAxes);
  742.   end;
  743. end;
  744.  
  745. function TCustomDBPlot.InsertPoint(iSeries: Integer; X, Y: Single): Integer;
  746. begin
  747.   if ((not FUpdating) and ReadOnly) then
  748.     Result := -1
  749.   else
  750.   begin
  751.     Result := TSeries(FSeriesList.Items[iSeries]).InsertPoint(X, Y);
  752.   end;
  753. end;
  754.  
  755. procedure TCustomDBPlot.ReplacePoint(iSeries, N: Integer; NewX, NewY: Single);
  756. begin
  757.   if ((not FUpdating) and ReadOnly) then exit;
  758.  
  759.   TSeries(FSeriesList.Items[iSeries]).ReplacePoint(N, NewX, NewY);
  760. end;
  761.  
  762. procedure TCustomDBPlot.Compress(iSeries: Integer; CompressRatio: Integer);
  763. begin
  764.   if ((not FUpdating) and ReadOnly) then exit;
  765.  
  766.   TSeries(FSeriesList.Items[iSeries]).Compress(CompressRatio);
  767. end;
  768.  
  769. procedure TCustomDBPlot.Contract(iSeries: Integer; TheStart, TheFinish: Integer);
  770. begin
  771.   if ((not FUpdating) and ReadOnly) then exit;
  772.  
  773.   TSeries(FSeriesList.Items[iSeries]).Contract(TheStart, TheFinish);
  774. end;
  775.  
  776. function TCustomDBPlot.DelPoint(iSeries: Integer; X, Y: Single; Confirm: Boolean): Integer;
  777. begin
  778.   if ((not FUpdating) and ReadOnly) then
  779.     Result := -1
  780.   else
  781.   begin
  782.     Result := TSeries(FSeriesList.Items[iSeries]).DelPoint(X, Y, Confirm);
  783.   end;
  784. end;
  785.  
  786. function TCustomDBPlot.DelPointNumber(iSeries: Integer; ThePoint: Integer; Confirm: Boolean): Integer;
  787. begin
  788.   if ((not FUpdating) and ReadOnly) then
  789.     Result := -1
  790.   else
  791.   begin
  792.     Result := TSeries(FSeriesList.Items[iSeries]).DelPointNumber(ThePoint, Confirm);
  793.   end;
  794. end;
  795.  
  796. function TCustomDBPlot.DelData(iSeries: Integer): Boolean;
  797. begin
  798.   if ((not FUpdating) and ReadOnly) then
  799.     Result := FALSE
  800.   else
  801.   begin
  802.     Result := TSeries(FSeriesList.Items[iSeries]).DelData;
  803.   end;
  804. end;
  805.  
  806. procedure TCustomDBPlot.Smooth(iSeries: Integer; SmoothOrder: Integer);
  807. begin
  808.   if ((not FUpdating) and ReadOnly) then exit;
  809.  
  810.   TSeries(FSeriesList.Items[iSeries]).Smooth(SmoothOrder);
  811. end;
  812.  
  813. procedure TCustomDBPlot.Sort(iSeries: Integer);
  814. begin
  815.   if ((not FUpdating) and ReadOnly) then exit;
  816.  
  817.   TSeries(FSeriesList.Items[iSeries]).Sort;
  818. end;
  819.  
  820. procedure TCustomDBPlot.Differentiate(iSeries: Integer);
  821. begin
  822.   if ((not FUpdating) and ReadOnly) then exit;
  823.  
  824.   TSeries(FSeriesList.Items[iSeries]).Differentiate;
  825. end;
  826.  
  827. procedure TCustomDBPlot.Integrate(iSeries: Integer);
  828. begin
  829.   if ((not FUpdating) and ReadOnly) then exit;
  830.  
  831.   TSeries(FSeriesList.Items[iSeries]).Integrate;
  832. end;
  833.  
  834. procedure TCustomDBPlot.MovingAverage(iSeries: Integer; Span: Integer);
  835. begin
  836.   if ((not FUpdating) and ReadOnly) then exit;
  837.  
  838.   TSeries(FSeriesList.Items[iSeries]).MovingAverage(Span);
  839. end;
  840.  
  841. {------------------------------------------------------------------------------
  842.     Procedure: TCustomDBPlot.StoreInDB
  843.   Description: Stores the current plot data in a database
  844.        Author: Mat Ballard
  845.  Date created: 03/02/2001
  846. Date modified: 03/02/2001 by Mat Ballard
  847.       Purpose: database management
  848.  Known Issues:
  849.      Comments: based on a post from: "Bruce Roberts" <ber@attcanada.xnet> on
  850.                Dynamic arrays in databases, Sun Feb 25 2001.
  851.  ------------------------------------------------------------------------------}
  852. procedure TCustomDBPlot.StoreInDB;
  853. var
  854. {$IFDEF MSWINDOWS}
  855.   TheBlobStream: TBlobStream;
  856. {$ENDIF}
  857. {$IFDEF LINUX}
  858.   TheBlobStream: TClientBlobStream;
  859. {$ENDIF}
  860. begin
  861.   if (Self.DataSource.DataSet.CanModify) then
  862.   begin
  863. {$IFDEF MSWINDOWS}
  864.     TheBlobStream := TBlobStream.Create (TBlobField(FDataLink.Field), bmWrite);
  865. {$ENDIF}
  866. {$IFDEF LINUX}
  867.     TheBlobStream := TClientBlobStream.Create (TBlobField(FDataLink.Field), bmWrite);
  868. {$ENDIF}
  869.     try
  870.       Self.SaveToStream(TMemoryStream(TheBlobStream));
  871.     finally
  872.       TheBlobStream.Free;
  873.     end;
  874.   end;
  875. end;
  876.  
  877.  
  878. {------------------------------------------------------------------------------
  879.     Procedure: TCustomDBPlot.LoadFromDB
  880.   Description: loads fresh plot data from a database
  881.        Author: Mat Ballard
  882.  Date created: 03/02/2001
  883. Date modified: 03/02/2001 by Mat Ballard
  884.       Purpose: database management
  885.  Known Issues: we need to create a memorystream because Misc.Readline barfs
  886.                because GetLineLengthFromStream barfs.
  887.      Comments: based on a post from: "Bruce Roberts" <ber@attcanada.xnet> on
  888.                Dynamic arrays in databases, Sun Feb 25 2001.
  889.  ------------------------------------------------------------------------------}
  890. procedure TCustomDBPlot.LoadFromDB;
  891. var
  892. {$IFDEF MSWINDOWS}
  893.   TheBlobStream: TBlobStream;
  894. {$ENDIF}
  895. {$IFDEF LINUX}
  896.   TheBlobStream: TStream;
  897. {$ENDIF}
  898.   TheMemoryStream: TMemoryStream;
  899. begin
  900.   Self.FSeriesList.ClearSeries;
  901. {$IFDEF MSWINDOWS}
  902.   TheBlobStream := TBlobStream.Create (TBlobField(FDataLink.Field), bmRead);
  903. {$ENDIF}
  904. {$IFDEF LINUX}
  905.   TheBlobStream :=
  906.     Self.FDataLink.DataSet.CreateBlobStream(TBlobField(FDataLink.Field), bmRead);
  907. {$ENDIF}
  908.   TheMemoryStream := TMemoryStream.Create;
  909.   try
  910.     if (TheBlobStream.Size > 20) then
  911.     begin
  912.       TheMemoryStream.LoadFromStream(TheBlobStream);
  913.       TheMemoryStream.Seek(0, soFromBeginning);
  914.       Self.LoadFromStream(TheMemoryStream);
  915.     end
  916.   finally
  917.     TheBlobStream.Free;
  918.     TheMemoryStream.Free;
  919.   end;
  920. end;
  921.  
  922. procedure TCustomDBPlot.UpdateRecord;
  923. begin
  924.   FDatalink.UpdateRecord;
  925. end;
  926.  
  927. end.
  928.