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

  1. unit Plot;
  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: Plot.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. Acknowledgements to:
  31.     Anders Melanders
  32.       - TGifImage (http://www.melander.dk)
  33.  
  34.     Edmund H. Hand
  35.       - pnglib
  36.     Jack Goman <jack@SharePower.VirtualAve.net>
  37.       - PngUnit
  38.     Eric Engler (http://www.geocities.com/SiliconValley/Network/2114/)
  39.       - TPngImage in Pnglib24a
  40.  
  41.     Atanas Stoyanov (http://www.poboxes.com/astoyanov/) and his marvelous
  42.       - MemProof
  43.  
  44.     Renate Schaaf (schaaf@math.usu.edu), 1993
  45.     Alin Flaider (aflaidar@datalog.ro), 1996
  46.     Hallvard Vassbotn (hallvard.vassbotn@c2i.net),
  47.       - TParser10
  48.     Stefan Hoffmeister (Stefan.Hoffmeister@Uni-Passau.de), 1997
  49.       - TParser10,
  50.       - Linux LoadStr and LoadBitmapFromResource bugfix,
  51.       - most useful comments on the kylix newsgroups
  52.     John Shemitz
  53.       - second most useful comments on the kylix newsgroups,
  54.         and the rotated Kylix text code.
  55.  
  56. Last Modified: 05/01/2001
  57. Current Version: 2.00
  58.  
  59. You may retrieve the latest version of this file from:
  60.  
  61.         http://Chemware.hypermart.net/
  62.  
  63. This work was created with the Project JEDI VCL guidelines:
  64.  
  65.         http://www.delphi-jedi.org/Jedi:VCLVCL
  66.  
  67. in mind.
  68.  
  69. Kylix issues:
  70.     - Yes, there is no printing (yet)
  71.     - Yes, there are no property editors (yet)
  72.     - Yes, there is no GIF support (yet)
  73.     - Note the peculiar work-arounds that apply to resources:
  74.       you have to patch QGraphics.
  75.     - No, everything else works.
  76.  
  77. Kylix tricks and traps:
  78.     - symlinks: put Symlinks from your home directory to your
  79.       development and kylix directories:
  80.       >cd ~
  81.       >ln -s /opt/kylix
  82.       >ln -s /opt/kylix/help kylixhelp
  83.       >ln -s /mnt/dos/delphi/components/tplot
  84.     - case sensitivity - filenames, resources, unit names, etc, etc, etc.
  85.     - permissions: suggest you make $(KYLIX)/bin user-writable, and put final binaries there
  86.     - put XKill on the taskbar - you'll need it !
  87.     - from the command line: "ps -A", then "kill nnn"
  88.     - CLX objects and classes don't correspond 100% to VCL ones:
  89.       there are some old properties and methods missing, and some new ones
  90.     - eg: QForms.TForm is different from Forms.TForm.
  91.       This means you can open a form saved from Delphi into Linux, and vice-versa,
  92.       _BUT_ you will get errors about non-existent properties. eg:
  93.           Delphi bitches about:
  94.             BorderStyle,
  95.             HelpType,
  96.             Color (different clXXXs),
  97.             Font.Weight
  98.           Kylix bitches about:
  99.             BorderStyle,
  100.       If you don't save a form from the current IDE, then it will hopefully compile
  101.       (and run) OK, BUT you may get exceptions when you open a dialog.
  102.  
  103. Known Issues:
  104.     - Printing does not (yet) work under Kylix.
  105.     - Property Editors do not work (yet) under Kylix.
  106.     - TToolBar DOES NOT WORK if used from the designer !
  107.       You must create it dynamically ! (See Normal1.pas)
  108.       Also, you cannot select individual buttons until AFTER you have
  109.       "View as Text" then "View As Form"
  110.     - $IFDEFs: TPlot _WAS_ used in a Delphi 1 application, and will be migrated
  111.       to Linux. $IFDEFs are therefore unavoidable.
  112.     - Explicit dereferencing (eg: XData^[i]) _IS_ required for compatibility
  113.       with Delphi 1. Besides, I prefer it to distinguish dynamic from static arrays.
  114.     - Since TPlotMenu is useless without TPlot, there is only the one
  115.       registration unit: TPlot_Reg.pas.
  116.     - TPlotMenu DOES NOT WORK under D1 - see PlotMenu.pas for details.
  117.     - Due to the infamous 64K limit, D1 popup menus are NOT context sensitive.
  118.     - if you work across different versions of Delphi, ALWAYS save any form from
  119.       the lowest version of Delphi (eg: Delphi 1), because otherwise the DFM
  120.       files will contain extra properties that will cause stream read errors in
  121.       lower versions of Delphi.
  122.  
  123. Comparison to TChart version 4 (in Delphi 5):
  124.     - Compare Normal.exe to TChartNormal.exe with "Fastline", then "Line" for symbols :
  125.     No Points           TPlot           TChart
  126.                         ms      M       ms      M
  127. No Symbols:
  128.     101 points          8.1    2.344    2.4   2.012
  129.     99,889 points      1554    3.164   2467   6.024
  130. Symbols, "Line" series
  131.     10,001              305    2.628    178   2.660
  132.     99,899             4546    3.292   2218   6.016
  133.                                       -9000
  134.     This was bizarre: the code said 2218 ms, but visually it took 9 s !
  135.     "Go Crazy": in this window resize test,
  136. Frames per minute: this is probably the best speed test:
  137.     10,001             101               44 (TChart then TPlot)
  138.                         88               45 (TPlot then TChart)
  139. Feature Comparison:
  140.     Click & drag       yes               no
  141.       objects
  142.     Popup menu         yes               no
  143.     Main menu          yes               no
  144.     Context sensitive  yes               no
  145.     Web images         yes               only GIF in Pro version
  146.     Web pages          yes               no
  147.     Sticky notes       yes               no
  148.     Dynamic,           yes               no
  149.       movable axes
  150.     Math functions:
  151.       User defined     yes               no
  152.       Average          yes              yes
  153.       Compression      yes               no
  154.       Contraction      yes               no
  155.       Differentiation  yes               no
  156.       Integration      yes               no
  157.       Linear Fits      yes               no
  158.       Moving Average   yes               no
  159.       Nearest Point    yes               no
  160.       Position         yes               no
  161.       Smoothing        yes               no
  162.       Splines          yes               no
  163.     True 3D plots      yes               Pro version
  164.     Database support   coming           yes
  165.  
  166. TO BE DONE:
  167.     - fix XStringData display bugs
  168.     - improve axis handling in 3D plots.
  169.     - Fix severe TPlotToolBar problem:
  170.       works fine when created dynamically, but dies in constructor with
  171.       "Component not found: TToolButton" when run from IDE placement.
  172.     - debug and thoroughly test TDBPlot
  173.     - get the HTML Help system working under Linux
  174.     
  175. Future Development:
  176.     - Printing under Kylix.
  177.     - Property Editors under Kylix.
  178.     - streaming of component properties sometimes does not work
  179.       eg: try setting Axis widths to different values
  180.     - implementation of GIFs under Linux:
  181.     - addition of a "Financial" menu, similar to "File", "Edit", etc, and
  182.       populate it with goodies like RSI.
  183.     - re-write the "DetermineMenuVisibility and ...Enabledness so that they can
  184.       control the visibility of buttons in TPlotToolBar.
  185.     - Marry Parser10 to a good minimization algorithm (eg: Simplex) so that users
  186.       can fit _ANY_ function.
  187.     - add some keyboard input ? not straightforward
  188.     - rationalization and rotation of 3D axes
  189.     - Walls for 3D ?
  190.     - line Contours ?
  191.     - 0 deg to 360 deg on Polars ?
  192.     - ptGantt ?
  193.     - drag points ?
  194.  
  195. History:
  196.  2.09  30 May 2001: Created Right Click and Drag popup menu - our first "gesture".
  197.                     Revised handling of its menuitems OnClick events and MouseUp methods. 
  198.  2.08  29 May 2001: renamed Zoom.pas to PlotZoom.pas to avoid namespace clash with RALib !!!
  199.                     Fixed scaling bugs with 3D and Bubble plots.
  200.                     Added Linearize and Zero functions.
  201.  2.07  16 May 2001: renamed ToolEdit.pas to Plottooledit.pas to avoid namespace clash with RXLib
  202.                     Reworked autoscaling of axes.
  203.                     Fixed some TDBPlot issues (FReadOnly replaced by FDataLink.ReadOnly),
  204.                     but still not happy with it.
  205.  2.06  16 May 2001: Made many changes to graphics handling.
  206.                     There are now Bitmap, Drawing, GIF and Png properties.
  207.                     Saving or copying these now becomes a one-liner.
  208.                     Great for all those web developers out there.
  209.                     Massive amount of work on the help file to bring it up to date.
  210.                     Create ActiveX control.
  211.  2.05  16 May 2001: Changed from Jack Goman's pngunit to Eric Engler's Pngimage
  212.                     to enable a Png property under Windows.
  213.  2.04  16 May 2001: Made Draw public
  214.  2.03  16 May 2001: Add Drawing property
  215.  2.02  11 May 2001: Add Png property
  216.  2.01  11 May 2001: Get SaveAsPNG working under Kylix with Jon Shemitz's help.
  217.  2.00  10 May 2001: Bump up version number and release.
  218.  1.81   9 May 2001: Added TDBPlot projects to Kylix project group
  219.  1.80   8 May 2001: Added XYFastAt property
  220.  1.79   7 May 2001: Modified TSeries.Draw to use a different algorithm if
  221.                     NoPts > 10000.
  222.  1.78   6 May 2001: Rewrote loading of binary files to handle XText data.
  223.  1.77   5 May 2001: Fixed bugs in reading of XText data from text files.
  224.  1.76   4 May 2001: Fixed bugs in display of XText data in Axis.
  225.  1.75   3 May 2001: Modified TCustomPlot.SetPlotMenu and TCustomPlot.SetPlotToolBar
  226.                     to correctly apply the Popupoptions to TPlotMenu and TPlotToolBar;
  227.                     also fixed bugs in the ApplyOptions methods of those two components.
  228.  1.74   2 May 2001: Added "ApplyOptions" to TPlotMenu.
  229.  1.73   2 May 2001: Added the CanConfigure property to TPlotToolBar
  230.  1.72   2 May 2001: Removed TPlotToolBar property editor -
  231.                     Visibility of buttons now set by TPlot.PopupOptions.
  232.  1.71   1 May 2001: Fixed numerous features/bugs in TPlotToolBar under Kylix,
  233.                     eg: "Buttons" vs "Controls", different indexing.
  234.  1.70  30 Apr 2001: Re-worked file and stream loading and saving,
  235.                     moving most of it into TSeriesList. 
  236.  1.69  29 Apr 2001: added PageButtons in Zoomed mode.
  237.  1.68  26 Apr 2001: Re-build BCB3 projects, and fix buglets associated with BCB compatibility:
  238.                     TPlotToolBar in particular.
  239.  1.67  26 Apr 2001: Change EditPoint to be D1 compatible.
  240.  1.66  25 Apr 2001: Re-work Parser, ParseData and ConvertTextData to handle
  241.                     matrix of Z values (Eugene Parsons).
  242.  1.65  25 Apr 2001: Total re-write of TSeries.DrawPie. Ain't it pretty now ?
  243.  1.64  25 Apr 2001: Modify ContourDetail to add cdVHigh, then bump all up by one,
  244.                     then make cdLow rectangles, cdMedium triangles, cdHigh points, cdVHigh filled.
  245.  1.63  22 Apr 2001: Added ZLength property, other fixes.
  246.  1.62  19 Apr 2001: Finally got TPlotToolBar working properly !
  247.  1.61  19 Apr 2001: Enabled multiline Title.Captions.
  248.  1.60  19 Apr 2001: Fixed Columnses visibility buglet.
  249.  1.59  19 Apr 2001: Moved Legend drawing code into TLegend, and added check marks.
  250.  1.58  19 Apr 2001: Implemented the lfSI format for output (M, K, etc)
  251.  1.57  19 Apr 2001: Fixed fiendish little bug that causes repeated redraw of plots on file opening.
  252.  1.56  18 Apr 2001: Added XTEXT support to text file IO; Problem: Binary file IO ?
  253.  1.55  18 Apr 2001: Added MultiJoin property to better manage High-Low-open-Close plots.
  254.  1.54  18 Apr 2001: Augmented the Import Parser to cope with XYZ triple text files.
  255.  1.53  16 Apr 2001: Fixed bugs in DataEditor.
  256.  1.52  16 Apr 2001: Fixed "ZoomOutClick" bugs.
  257.  1.51  16 Apr 2001: Implemented "NewSeriesClick".
  258.  1.50  11 Apr 2001: Added ptBubble PlotType, and all associated methods and variables.
  259.  1.49   9 Apr 2001: Fixed/upgraded Parser, ConvertTextData and ParseData to import
  260.                     3D data.
  261.  1.48   4 Apr 2001: Implemented Functions using TParser10- eat your heart out David B !
  262.  1.47   3 Apr 2001: Routed all dialog geometries into Misc.SetDialogGeometry()
  263.  1.46   2 Apr 2001: ... then fixed Linux color bug in the text output on Pie graphs
  264.  1.45   1 Apr 2001: Finally nailed correct positioning of the text output on Pie graphs
  265.  1.44  29 Mar 2001: Much work fixing Linux bugs: LoadStr for string resources (menus),
  266.                     loading bitmaps (many thanks to Stephan Hoffmeister), TCanvas.Pie, etc.  
  267.  1.43  28 Mar 2001: Major overhaul of dialogs: add "Apply" button and code to most.
  268.  1.42  27 Mar 2001: Get property editors to compile. "About" works once, but then
  269.                     Kylix freezes whenever TPlot is installed.
  270.  1.41  27 Mar 2001: Fix Polygon issue, somehow. And other Kylix buglets.
  271.  1.40  23 Mar 2001: Kylix finally arrives. Fix many issues, but not all. See "Traps" below.
  272.  1.39  15 Mar 2001: Changed licensing from MPL to QPL.
  273.                     In practise, this only affects commercial developers.
  274.  1.38  15 Mar 2001: Added TPlotComponentEditor to Plot_reg.pas to give design-time menus.
  275.  1.37  15 Mar 2001: Revise TSeries.DrawPie to add labels.
  276.  1.36  14 Mar 2001: Revise TSeries.XStringData extensively.
  277.  1.35  12 Mar 2001: Surface many TSeriesList methods in TPlot for TDBPlot to override.
  278.  1.34   7 Mar 2001: Revise the OnStyleChange/OnDataChange events in TSeries and TSeriesList
  279.  1.33   2 Mar 2001: Begin work on TDBPlot.
  280.  1.32   2 Mar 2001: We have a renaming frenzy, to make the purpose of the major
  281.                     series manipulation functions more obvious.
  282.                       Add         -> AddSeries
  283.                       AddExternal -> AddExternalSeries
  284.                       AddInternal -> AddInternalSeries
  285.                       AddSlice    -> AddData
  286.                     My apologies to all existing users. This will break existing
  287.                     code, but fixing it should be trivial.
  288.  1.31   1 Mar 2001: Rename TSymbol elements to have two leading characters: fixes RTTI bug.
  289.  1.30   1 Mar 2001: Replace color selection combo boxes with TColorEdit.
  290.  1.29   1 Mar 2001: Replace most combobox items with RTTI generated strings.
  291.  1.28  28 Feb 2001: Add Grids due to popular demand (Yuck !).
  292.  1.27  28 Feb 2001: Add the TAxis.StepStart property.
  293.                     Add a scale to ptContour plots.
  294.  1.26  27 Feb 2001: Fix bugs in TSeries.GetNearestPieSlice, and refine TSeries.Outline.
  295.  1.25  26 Feb 2001: Column, Stacked Column and 100% Column plots added to
  296.                     GetTheClickedObject (and TSeriesList.GetNearestPoint).
  297.                     Contemplate releasing next version as 2.0:
  298.                     reason: TPlot now has 10 different plot types, instead of 1 !
  299.  1.24  22 Feb 2001: Refine DrawContour. Implement true WMF and printing. Now looks beautiful !
  300.                     Add usage hints to PropertiesEdit dialog box.
  301.  1.23  21 Feb 2001: Pie plots added to GetTheClickedObject
  302.  1.22  20 Feb 2001: Add OnStyleChange event. Route all "Refresh"s through DoStyleChange.
  303.                     Complete first go at DrawContour.
  304.                     Add ContourDetail property.
  305.  1.21  1 Feb  2001: Add ZAngle, ZLink properties.
  306.                     Rename pSeries.pas unit to Data.pas, SerList.pas to Datalist.pas
  307.  1.20 14 Jan  2001: Modify TSeriesList to add ZData (for 3D)
  308.                     Create TAngleAxis class, and implement a ZAxis for 3D.
  309.                     Add the ptError, ptPie, ptPolar and pt3DWire PlotTypes.
  310.                     Create the NoMath unit, move some stuff into it from Misc.
  311.  1.19 9  Dec  2000: Modify movement of Note Pointer: place before selection of
  312.                     series, and postpend to movement of the Note text.
  313.  1.18 8  Dec  2000: Refine SetPlotType so that each plot type initially displays
  314.                     its features better.
  315.  1.17 6  Dec  2000: Add ptStack and ptNormStack PlotTypes types,
  316.                     and implement their drawing routines.
  317.  1.16 1  Dec  2000: Add ColumnGap property.
  318.  1.15 16 Nov  2000: Implement TNote functionality: NewNote, DeleteNote, etc.
  319.  1.14 13 Nov  2000: Add Misc.TextOutVertical, and employ in various locations;
  320.                     benefit: will work under Linux (look into native X calls later).
  321.  1.13  7 Nov  2000: Add sLeftDash and sRightDash to TSymbol, and to TSeries.DrawSymbol.
  322.  1.12  1 Nov  2000: Create TNote sub-component.
  323.  1.11 16 Oct  2000: Add "Compress Series" and "Compress All Series", and associated
  324.                     CompressSeriesClick and CompressAllSeriesClick. Tidied up:
  325.                     Contract originally compressed; now it really does contract.
  326.                     Remove ability to clone X Axis.
  327.                     Add LabelText to Axes, mainly for Column usage.
  328.                     Fix Instruction property bug in IDE.
  329.  1.10  9 Oct  2000: Add and integrate Column capability with TPlotType type and PlotType properties
  330.                     and TSeriesList.DrawColumns.
  331.                     Consolidate some TCustomPlot.xxxClick methods.
  332.                     ****************************
  333.                     *** Borland BC++ support ***
  334.                     ****************************
  335.  1.02 25 Sept 2000: add and integrate High-Low-Close capability with
  336.                     TSeriesList.DrawMultiple and TSeriesList.DrawHistoryMultiple;
  337.                     Hide menu visibility routine from D1 to avoid 64K problems.
  338.  1.01 21 Sept 2000: fix FontWidth bug in TAxis.Draw
  339.                     add TPlotType type,
  340.                     add PlotType and Multiplicity properties
  341.                     add LabelText property to TAxis (for columns)
  342.       18 Sept 2000: delete PlotList.pas (replaced by SerList.pas);
  343.                     remove GifPng from Plot dpks;
  344.                     re-create saved files.
  345.  1.00 13 Sept 2000: Release version 1.00
  346.  
  347. -----------------------------------------------------------------------------}
  348.  
  349. interface
  350.  
  351. uses
  352.   Classes, SysUtils,
  353. {$IFDEF NO_MATH}NoMath,{$ELSE}Math,{$ENDIF}
  354. {$IFDEF WINDOWS}
  355.   WinTypes, WinProcs,
  356.   Buttons, Clipbrd, Controls, Dialogs, Extctrls, Forms, Graphics, Menus, Printers, Stdctrls,
  357. {$ENDIF}
  358. {$IFDEF WIN32}
  359.   Windows,
  360.   Buttons, Clipbrd, ComCtrls, Controls, Dialogs, Extctrls, Forms, Graphics, Menus, Printers, Stdctrls,
  361. {$ENDIF}
  362. {$IFDEF LINUX}
  363.   Types, Untranslated,
  364.   QTypes, QButtons, QClipbrd, QComCtrls, QControls, QDialogs,
  365.   QExtctrls, QForms, QGraphics, QImgList, QMenus, QStdctrls,
  366. {$ENDIF}
  367.  
  368. {$IFDEF DELPHI1}
  369.   Metafile,
  370. {$ENDIF}
  371. {$IFDEF GIF}
  372.   GIFImage,
  373. {$ENDIF}
  374. {$IFDEF PNG}
  375.   {$IFDEF MSWINDOWS}
  376.   Pngimage,
  377.   {$ENDIF}
  378. {$ENDIF}
  379.  
  380.   Aboutdlg, Axis, Axisedit, Data, Misc, Optnsdlg, Parser,
  381.   Plotdefs, PlotZoom, Propedit, Datalist, Seredit, Titles;
  382.  
  383. resourcestring
  384.   sInstruction1 = 'Click and Drag to move, Right Click and Drag to Act, Double-Click to edit,';
  385.   sInstruction2 = 'Right-Click for Popup, and Shift-Click and Drag to Zoom In !';
  386.   sLeft = 'Left';
  387.   sTop = 'Top';
  388.   sRight = 'Right';
  389.   sBottom = 'Bottom';
  390.   sBorder = 'Border';
  391.   sseconds = 'seconds';
  392.   smVolts = 'mVolts';
  393.   sYAxis = 'Y-Axis';
  394.   sPlotTitle = 'Plot Title';
  395.   sLegend = 'Legend';
  396.   sGetSeriesError = 'There is no series %d: valid indices are from 0 to %d';
  397.   sPaintError = 'TCustomPlot.Paint: Canvas is nil !';
  398.   sDrawError = 'TCustomPlot.Draw: ACanvas is nil !';
  399.   sTraceError = 'TCustomPlot.Trace: Canvas is nil !';
  400.   sFlashEditHint = 'Type in the new caption, then press <-Enter, or Escape to cancel.';
  401.   sMoveThe = 'Move the ';
  402. {Modes selection in TCustomPlot.ModeClick:}
  403.   sMode1 = 'Display Mode ?';
  404.   sMode2 = 'How do you want to display the data when a new point is added?';
  405.   sMode3 = 'Normal - expand the Axes if necessary';
  406.   sMode4 = 'None - do nothing';
  407.   sMode5 = 'Run - if neccessary, expand the Y-Axis but double the X-Axis';
  408.   sMode6 = 'History - only show the most recent data';
  409.   sDualInstruction = 'Click and Drag over the SECOND region';
  410.   sFit = ' to fit';
  411.   sLn = 'Ln';
  412.   sRSquare = 'R-Square';
  413.   sAddDataError = 'AddData: you must add between 1 and %d points !';
  414.   sHideInstruction = 'Click on the object you want to hide';
  415.   sClickNear = 'Click near the point you want';
  416.   sAt = 'at';
  417.   sPosition1 = 'Click on the position you want the details of';
  418.   sPosition2 = 'The screen co-ordinates are (%d, %d),';
  419.   sPosition3 = 'and the Position is (';
  420.   sTheNearestPointIs = 'The nearest point is #';
  421.   sHistoryRange = 'History Range';
  422.   sParseData1 = 'Minor problem: you can only look at %d lines of data !';
  423.   sParseData2 = 'I am befuddled by the XSeriesCol !';
  424.   sLBF = 'Click and Drag over the region to fit.';
  425.   s2RLBF = 'Click and Drag over the FIRST region to fit.';
  426.   sSmoothing1 = 'Smoothing ';
  427.   sSmoothing2 = 'Enter the Smoothing Order (2..20)';
  428.   sSmoothFail = 'Smoothing Failed !';
  429.   sSpline1 = 'Cubic Spline';
  430.   sSpline2 = 'Please enter the number of divisions';
  431.   sSpline3 = 'Cubic Spline of ';
  432.   sCompress1 = 'Cannot Compress %s !';
  433.   sCompress2 = '%d other series depend on it !';
  434.   sCompress3 = 'It depends on the X Data in %s !';
  435.   sCompress4 = 'Compressing ';
  436.   sCompress5 = 'Enter the Compression Ratio (2..20)';
  437.   sCompress6 = 'Compression Failed !';
  438.   sCompressAll1 = 'Compressing ALL Series';
  439.   sContract1 = 'Cannot Contract %s !';
  440.   sContract2 = 'Click and Drag over the (X-) data to keep - ';
  441.   sContract3 = '  all data outside this region is deleted.';
  442.   sLegend1 = 'Legend direction ?';
  443.   sLegend2 = 'How do you want to display the Legend ?';
  444.   sHorizontally = 'Horizontally';
  445.   sVertically = 'Vertically';
  446.   sNewNote1 = 'Move the cursor to the new note pointer then click';
  447.   sEditFont1 = 'Edit which Font ?';
  448.   sEditFont2 = 'Which Font you want to edit ?';
  449.   sEditFont3 = 'Plot Title';
  450.   sEditFont4 = 'X-Axis Title';
  451.   sEditFont5 = 'Y-Axis Title';
  452.   sEditFont6 = 'Secondary Y-Axis Title';
  453.   sEditFont7 = 'X-Axis Labels';
  454.   sEditFont8 = 'Y-Axis Labels';
  455.   sEditFont9 = 'Secondary Y-Axis Labels';
  456.   sEditFont10 = 'Legend';
  457.   sEditFont11 = 'Result';
  458.   sWhichNote = 'Which Note ?';
  459.   sWhichNoteDel = 'Which Note do you want to Delete ?';
  460.   sWhichSeries = 'Which Series ?';
  461.   sWhichSeries2 = 'Which Series you want to work on ?';
  462.   sWhichAxis = 'Which Axis ?';
  463.   sWhichAxis2 = 'Which Axis you want to work on ?';
  464.   sOpen = 'Open';
  465.   sClearOverlays = 'There are no Overlays to Clear !';
  466.   sOverlay1 = 'Overlay Data As';
  467.   sSaveImage1 = 'Save Image As';
  468.   sSaveAs1 = 'Save Data As';
  469.   sLoadFromFile1 = 'This file has no binary marker !';
  470.   sDoesNotExist = ' does not exist !';
  471.   sInvalidTag = 'invalid Tag %d';
  472.   sTagNotMatch = 'Tags do not match !';
  473.   sZoomIn = 'Click and drag over the region you want to zoom in on';
  474.   sFrom = ' from ';
  475.   sTo = ' to ';
  476.   sIs = ' is ';
  477.   sIntegral1 = 'The integral of ';
  478.   sIntegral2 = 'Click and Drag over the (X-) region to calculate the Integral';
  479.   sHighLow1 = 'Highs and Lows';
  480.   sHighLow2 = 'What do you want to do ?';
  481.   sHighLow3 = 'Hide Highs and Lows';
  482.   sHighLow4 = 'Show Highs';
  483.   sHighLow5 = 'Show Lows';
  484.   sHighLow6 = 'Show Highs and Lows';
  485.   sMovingAverage1 = 'Calculation of the Moving Average';
  486.   sMovingAverage2 = 'Enter the number of points to average over';
  487.   sMovingAverage3 = 'Moving Average Failed !';
  488.   sAverage1 = 'The Average of ';
  489.   sAverage2 = 'Click and Drag over the (X-) region to calculate the Average';
  490.   sLinearize = 'Click and Drag over the (X-) region that you want Linearized';
  491.   sZero = 'Click and Drag over the (X-) region that you want to set to Zero';
  492.   sCopyOf = 'Copy of ';
  493.   sDeleteAxis1 = 'Cannot delete Axis #%d; Secondary Axes are numbered from 2 to %d';
  494.   sDeleteAxis2 = 'Delete Secondary Axis';
  495.   sDeleteAxis3 = 'Are you sure you want to delete ';
  496.   sSetNoYAxes1 = 'You must be joking ! I only support 15 Y Axes - not %d !';
  497.   sThisFile = 'this file';
  498.   sSave = 'Save ';
  499.   sBeforeClose = ' before closing it ?';
  500.   sFileHasChanged = 'File has Changed';
  501.   sSaveFile = 'Save File';
  502.   sCreatedBy1 = 'Author';
  503.   sCreatedBy2 = 'Please enter your name';
  504.   sNewSeries1 = 'New Series';
  505.   sNewSeries2 = 'Does this new series use the X Data of an existing series ?';
  506.   sNewSeries3 = 'No - it is independent';
  507.  
  508. const
  509.   SUBHEADER = 'Subheader';
  510.  
  511. {$IFDEF DELPHI1}
  512.   DEF_EXTENSION = 'plt';
  513.   PROP_EXTENSION = 'prp';
  514. {$ELSE}
  515.   DEF_EXTENSION = 'plot';
  516.   PROP_EXTENSION = 'props';
  517. {$ENDIF}
  518.  
  519.   crScope = 1;
  520.   crX = 2;
  521.  
  522.   ImageExtensions: array[0..4] of string =
  523.     ('wmf', 'emf', 'bmp', 'gif', 'png');
  524.  
  525.   PICTURE_TYPES =
  526.     'Metafile (picture)|*.wmf'
  527.     + '|Enhanced Metafile (picture)|*.emf'
  528.     + '|Bitmap|*.bmp'
  529. {$IFDEF GIF}
  530.     + '|Compuserve GIF|*.gif'
  531. {$ENDIF}
  532. {$IFDEF PNG}
  533.     + '|Web Graphic|*.png'
  534. {$ENDIF}
  535.     ;
  536.  
  537.  
  538. type
  539. {NB: many other types are in PlotDefs.pas}
  540.   TOnPaintEvent = procedure(Sender: TObject; ACanvas: TCanvas) of object;
  541.  
  542.   TOnFileEvent = procedure(Sender: TObject; TheFile: String) of object;
  543. {When a file is opened or closed, the app can be notified of the new file name
  544.  using this event.}
  545.  
  546.   TOnHeaderEvent = procedure(Sender: TObject; TheStream: TMemoryStream) of object;
  547. {When data is opened, the "user-added" Header (eg: the run date, flow rate,
  548.  comments, etc) is passed back to the user for processing.}
  549.  
  550.   TOnRequestHeaderEvent = procedure(Sender: TObject; TheStream: TMemoryStream) of object;
  551. {When data is saved or copied, then the "user" can add additional data via the
  552.  Header: eg: the run date, flow rate, comments, etc.}
  553.  
  554.   TOnRequestHTMLHeaderEvent = procedure(Sender: TObject; Header: TStringList) of object;
  555. {When data is saved or copied, then the "user" can add additional data via the
  556.  Header: eg: the run date, flow rate, comments, etc.}
  557.  
  558.   TOnSelectionEvent = procedure(Sender: TObject; Sel: TRect) of object;
  559. {When the user clicks and drags over a region, this event is fired.}
  560.  
  561.   TOnDualSelectionEvent = procedure(Sender: TObject; Sel1, Sel2: TRect) of object;
  562. {When the user clicks and drags over TWO regions, this event is fired.}
  563.  
  564.  
  565. {******************************************************************************}
  566.   TCustomPlot = class(TCustomPanel)
  567.   private
  568. {property editor variables:}
  569.     FAbout: String;
  570.     FAxesProperties: String;
  571.     FDataProperties: String;
  572.     FSeriesProperties: String;
  573. {The AxisList is created and managed in the Plot unit and TCustomPlot component.
  574.  The specific axes are:
  575.    0 .. X Axis
  576.    1 .. Primary Y Axis
  577.    2 .. Secondary Y Axis
  578.    3 .. Tertiary Y Axis
  579.    4 .. etc.}
  580.     FAxisList: TList;
  581.     FBorder: TBorder;
  582.     FBubbleSize: TPercent;
  583.     FColumnGap: TPercent;
  584.     FContourDetail: TContourDetail;
  585.     FGrid: TGridType;
  586.     FGridStyle: TPenStyle;
  587.     FHelpFile: String;
  588.     FInstructions: TStringList;
  589. {$IFNDEF DELPHI1}
  590.     FCreatedBy: String;
  591.     FDescription: String;
  592. {$ENDIF}
  593.  
  594.     FDisplayMode: TDisplayMode;
  595.     FDisplayHistory: Single;
  596.     FEditable: Boolean;
  597.     FDefaultExtension: String;
  598.  
  599.     FFileName,      {D:\Data\Delphi\Plot\Test3.csv}
  600.      {GetFileExtension, {csv}
  601.      {GetFileDriveDir,  {D:\Data\Delphi\Plot}
  602.      {GetFileName,      {Test3.csv}
  603.      {GetFileRoot,      {Test3}
  604. {where are the file types ?}
  605.      OpenDriveDir,      {NB: SavePath == FileDriveDir}
  606.      OverlayDriveDir,   {T:\Projects\}
  607.      ImageDriveDir,     {D:\Data\Images}
  608.      PropsFileName: String;
  609. {What file types ?}
  610.      OpenFilterIndex,
  611.      SaveFilterIndex,
  612.      ImageFilterIndex: Integer;
  613.  
  614.     FHighFont: TFont;
  615.     FMenuTag: Integer;      {may publish later}
  616.     FMovable: Boolean;
  617.     FMultiplePen: TPen;
  618.     FMultiplicity: Byte;
  619.     FMultiJoin1, FMultiJoin2: Integer;
  620.     FPieRowCount: Byte;
  621.     FPolarRange: Single;
  622.     FOutlineWidth: Integer;
  623.  
  624.     FPageButtons: array[0..3] of TBitmap;
  625.  
  626.     FPlotMenu: TMainMenu;
  627.     FPlotToolBar: TToolBar;
  628. {$IFDEF DELPHI4_UP}
  629.     //FPlotActionList: TActionList;
  630. {$ENDIF}
  631.     FPlotType: TPlotType;
  632.     FPopupOptions: TPopupOptions;
  633. {$IFDEF MSWINDOWS}
  634.     FPrintOrientation: TPrinterOrientation;
  635. {$ENDIF}
  636. {$IFDEF LINUX}
  637.     FPrintOrientation: Untranslated.TPrinterOrientation;
  638. {$ENDIF}
  639.     FSaveOptions: TSaveOptions;
  640.      FAsText: Boolean;  {the current, which depends on the file type and is ORed with FSaveOptions}
  641.     FXAxis: TAxis;
  642.     FYAxis: TAxis;
  643.     FZAxis: TAngleAxis;
  644.     FZLink: Boolean;
  645.  
  646.     FXYFastAt: Longint;
  647.  
  648.     FOnAfterPaint: TOnPaintEvent;
  649.     FOnAfterDraw: TOnPaintEvent;
  650.     FOnBeforePaint: TOnPaintEvent;
  651.     FOnBeforeDraw: TOnPaintEvent;
  652.     FOnStyleChange: TNotifyEvent;
  653.     FOnDataChange: TNotifyEvent;
  654.     FOnFileOpen: TOnFileEvent;
  655.     FOnFileClose: TOnFileEvent;
  656.     FOnHeader: TOnHeaderEvent;
  657.     FOnHeaderRequest: TOnRequestHeaderEvent;
  658.     FOnHTMLHeaderRequest: TOnRequestHTMLHeaderEvent;
  659.     FOnSelection: TOnSelectionEvent;
  660.     FOnDualSelection: TOnDualSelectionEvent;
  661.  
  662. {the location of the graph title:}
  663.     FTitle: TTitle;
  664. {The results of things like least-squares fits:}
  665.     FResult: TCaption;
  666. {The Legend of Series}
  667.     FLegend: TLegend;
  668.  
  669. {the four borders, clickable by the user:}
  670.     LeftBorder: TRectangle;
  671.     TopBorder: TRectangle;
  672.     RightBorder: TRectangle;
  673.     BottomBorder: TRectangle;
  674.  
  675. {Ignore changes in sub-components during painting:}
  676.     IgnoreChanges: Boolean;
  677.  
  678.     FScreenJob: TScreenJob;
  679.  
  680. {The list of (TRectangle descended) objects on screen:}
  681.     ScreenObjectList: TList;
  682.     NoBasicScreenObjects: Integer;
  683. {The list of notes:}
  684.     //NoteList: TList;
  685.     NoteCount: Integer;
  686.  
  687. {The timer to start click-and-drag operations:}
  688.     MouseTimer: TTimer;
  689. {the position of the mousedown:}
  690.     MouseStart: TPoint;
  691.  
  692. {The starting point of click-and-drag operations:
  693.     MouseStart: TPoint; - replaced by Selection1}
  694. {which object(s) were clicked ?}
  695.     ClickedObjectType: TObjectType;
  696.     pClickedObject: Pointer;
  697.     SecondClickedObjectType: TObjectType;
  698.     pSecondClickedObject: Pointer;
  699. {the starting position of the object:}
  700.     ClickedObjectOffset: TPoint;
  701.  
  702. {the parameters of the line of best fit:}
  703.     Slope, Intercept: Single;
  704. {The rectangular outline of a ScreenObject that is dragged around the screen:}
  705.     Selection: TRectangle;
  706. {The first selection in a Dual Selection operation:}
  707.     Sel1, Sel2: TRect;
  708.     
  709. {Popup menus:}
  710.     FPlotPopUpMenu: TPopupMenu;
  711.     FDragPopUpMenu: TPopupMenu;
  712.     WhichPopUpMenu: TPopupMenu;
  713.     WhichPopUpItems: array[0..1] of TMenuItem;
  714.  
  715. {the in-place editor:}
  716.     FFlashEdit: TEdit;
  717.  
  718. {the currently selected (eg: by a mouse-click) series:}
  719.     TheSeries: Integer;
  720.     pSeries: TSeries;
  721.     ThePointNumber: Integer;
  722.  
  723. {the currently selected (eg: by a mouse-click) Axis:}
  724.     TheAxis: Integer;
  725.     pAxis: TAxis;
  726.  
  727. {The clipboard format number for HTML:}
  728.     ClipBoardFormatForHTML: Integer; {aka CF_HTML}
  729.  
  730. {Overlay Management:}
  731.     FirstOverlay: Integer;
  732.  
  733.     BevelGap: Integer;
  734.  
  735.     FileExtensions: array[0..3] of String;
  736.    {= (
  737.     FDefaultExtension,
  738.     'csv',
  739.     'txt',
  740.     '*');}
  741.  
  742.     FileTypes: String;
  743.   {=
  744.     'Plot Files|*.' + FDefaultExtension
  745.     + '|Comma Sep Var Files|*.csv'
  746.     + '|Text Files|*.txt'
  747.     + '|All Files|*.*';}
  748.  
  749.  
  750.  
  751. {Get functions}
  752.     function GetClickAndDragDelay: Integer;
  753.     function GetNoSeries: Word;
  754.     function GetNoYAxes: Integer;
  755.     function GetSeries(Index: Integer): TSeries;
  756.     function GetNoteFromUser: Boolean;
  757.     function GetSeriesFromUser: Boolean;
  758.     function GetAxisFromUser(StartAxis: Word): Boolean;
  759.     function GetFilterIndex(Ext: String): Integer;
  760. {$IFDEF COMPILER4_UP}
  761. {while TImageList exists from Delphi 2 onwards, TMenu and TPopupMenu
  762.  do not have an Images property until Delphi 4}
  763.     function GetImages: TImageList; {TCustomImageList}
  764.     procedure SetImages(Value: TImageList);
  765. {$ENDIF}
  766.  
  767. {SetProcedures:}
  768. {The main geometry manager.}
  769.     procedure SetAxisDimensions;
  770. {Sets the behaviour upon adding new data points.}
  771.     procedure SetDisplayModeHistory(HistoryValue: Single; ScalingValue: TDisplayMode);
  772. {$IFNDEF DELPHI1}
  773.     {Puts CreatedBy and Description into the metafile.}
  774.     procedure SetMetafileDescription;
  775. {$ENDIF}
  776.  
  777. {Responding to mouse events, click & drag:}
  778.     procedure GetTheClickedObject(X, Y: Integer);
  779.     procedure MouseTimeOut(Sender: TObject);
  780.     procedure MoveTheClickedObjectTo(X, Y: Integer);
  781.     procedure OutlineTheClickedObject;
  782.     procedure OutlineTheSelection;
  783.     procedure SetResult(Slope, Intercept, Rsq: Single);
  784.     procedure StretchTheClickedObjectTo(X, Y: Integer);
  785.     procedure SwapEnds;
  786. {These two respond to a user choice between overlaying objects:}
  787.     procedure MoveTheClickedObjectClick(Sender: TObject);
  788.     procedure MoveSecondClickedObjectClick(Sender: TObject);
  789. {Sets the width of the outline for screen objects like lines: axes and borders.}
  790.     procedure CreateFlashEditor;
  791.     procedure FlashEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  792. {Processes key presses from the in-place editor.}
  793.     procedure FlashEditExit(Sender: TObject);
  794.  
  795.   protected
  796.     FSeriesList: TSeriesList;
  797. {Huh ?! Why protected for both the internal variable and the property ?}
  798. {Because the property is later Published in TPlot, and TDBPlot needs access to
  799.  the internal variable, but still has to hide the property.}
  800.  
  801.     function GetMultiJoin: String;
  802.     function GetZAngle: Word;
  803.     function GetZLength: Word;
  804. {Property Set Procedures:}
  805.     procedure SetZAngle(Value: Word);
  806.     procedure SetZLength(Value: Word);
  807.     procedure SetZLink(Value: Boolean);
  808.     procedure SetXYFastAt(Value: Longint);
  809.     procedure SetBubbleSize(Value: TPercent);
  810.     procedure SetColumnGap(Value: TPercent);
  811.     procedure SetContourDetail(Value: TContourDetail);
  812.     procedure SetGrid(Value: TGridType);
  813.     procedure SetGridStyle(Value: TPenStyle);
  814.     procedure SetDefaultExtension(Value: String);
  815.     procedure SetDefaults;
  816.     procedure SetDisplayMode(Value: TDisplayMode);
  817.     procedure SetHistory(Value: Single);
  818.     procedure SetInstructions(Value: TStringList);
  819. {Handles file names for saving and opening:}
  820.     procedure SetFileName(Value: String);
  821.     procedure SetNoYAxes(Value: Integer);
  822.     procedure SetPlotType(Value: TPlotType);
  823.     procedure SetPolarRange(Value: Single);
  824.     procedure SetPopupOptions(Value: TPopupOptions);
  825.     procedure SetOutlineWidth(Value: Integer);
  826.     procedure SetMultiplicity(Value: Byte);
  827.     procedure SetMultiplePen(Value: TPen);
  828.     procedure SetMultiJoin(Value: String);
  829.     procedure SetPieRowCount(Value: Byte);
  830.     procedure SetNoSeries(Value: Word); virtual;
  831.     procedure SetClickAndDragDelay(Value: Integer);
  832.     procedure SetOnSelection(Value: TOnSelectionEvent);
  833.     procedure SetOnDualSelection(Value: TOnDualSelectionEvent);
  834.  
  835.     {procedure StyleChange(Sender: TObject);}
  836. {Responds to appearance changes in subcomponents.}
  837.     {procedure DataChange(Sender: TObject); }
  838. {Responds to changes in the basic data.}
  839.  
  840.  
  841. {Copying data:}
  842.     procedure CopyText; virtual;
  843. {Copies the data as tab-delimited text to the Clipboard, with any
  844.  TCustomPlot.Owner added header.}
  845.     procedure CopyHTML(Format: Word); virtual;
  846. {Copies the data as HTML to the Clipboard in CF_HTML format, with any
  847.  TCustomPlot.Owner added header.}
  848. {Copying pictures:}
  849.     procedure CopyBitmap; virtual;
  850.  
  851.     function GetBitmap: TBitmap; virtual;
  852. {Does what it says.}
  853. {$IFDEF MSWINDOWS}
  854.     function GetDrawing: TMetafile; virtual;
  855. {$ENDIF}
  856. {$IFDEF LINUX}
  857.     function GetDrawing: TDrawing; virtual;
  858. {$ENDIF}
  859. {$IFDEF GIF}
  860.     function GetGIF: TGIFImage; virtual;
  861. {$ENDIF}
  862. {$IFDEF PNG}
  863.   {$IFDEF MSWINDOWS}
  864.     function GetPng: TPngImage; virtual;
  865.   {$ENDIF}
  866.   {$IFDEF LINUX}
  867.     function GetPng: TBitmap; virtual;
  868.   {$ENDIF}
  869. {$ENDIF}
  870.  
  871.     procedure CopyDrawing(Enhanced: Boolean); virtual;
  872. {Does what it says.}
  873.  
  874.     procedure CreateMenus;
  875. {Creates the three popup menus.}
  876.  
  877.     procedure CreatePageButtons;
  878.     procedure DestroyPageButtons;
  879.     procedure PageButtonClick(Index: Integer);
  880.  
  881.     procedure DoStyleChange(Sender: TObject); dynamic;
  882.     procedure DoDataChange(Sender: TObject); dynamic;
  883.     procedure DoFileClose(AFileName: String); dynamic;
  884.     procedure DoFileOpen(AFileName: String); dynamic;
  885.     procedure DoHeader(TheStream: TMemoryStream); dynamic;
  886.     procedure DoHeaderRequest(TheStream: TMemoryStream); dynamic;
  887.     procedure DoHTMLHeaderRequest(TheHeader: TStringList); dynamic;
  888.     procedure DoSelection(Sel1: TRect); dynamic;
  889.     procedure DoDualSelection(Sel1, Sel2: TRect); dynamic;
  890.  
  891. {File manipulation:}
  892.     procedure OpenProperties(AFileName: String);
  893. {Saves the Plot Properties to a file.}
  894.     procedure SaveTheProperties(AFileName: String);
  895. {Saves the Plot Properties to a file.}
  896.  
  897.     function CanPaste: Boolean;
  898. {Can we paste data from the Clipboard into TPlot ?}
  899.     procedure DblClick; override;
  900. {Some items - ie: the Title Captions, can be edited directly.}
  901.     {procedure KeyDown(var Key: Word; Shift: TShiftState); override;}
  902. {This processes certain key strokes.}
  903.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  904. {Implements dragging with the mouse.}
  905.     procedure MouseMove(Shift: TShiftState; X,Y: Integer); override;
  906. {Further implements dragging with the mouse.}
  907.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,Y: Integer); override;
  908. {Implements dragging with the mouse, and right clicking for a popup menu.}
  909.     procedure ProcessClickedObject(pObject: Pointer; TheObjectType: TObjectType); virtual;
  910. {Applies effects of clicking and dragging to the selected object.}
  911.  
  912. {Paint and Draw:}
  913.     procedure DrawContourColors(ACanvas: TCanvas);
  914. {This draws the scale of colours in a contour plot - it is called by Draw.}
  915.     procedure DrawGrid(ACanvas: TCanvas);
  916. {This draws grid for xy-type plots - it is called by Draw.}
  917.     procedure Paint; override;
  918. {The normal paint procedure. Most of the work is done in Draw.}
  919.     procedure DrawInstructions;
  920. {Just draws the instructions.}
  921.     procedure Resize; override;
  922. {The normal Resize procedure - it manages screen geometry.}
  923.     procedure ZeroScreenStuff; dynamic;
  924. {This re-initializes all the mouse-selection related variables}
  925.  
  926. {$IFNDEF DELPHI1}
  927.     procedure DetermineMenuVisibility;
  928. {Sets the Visibility of the items of the internal Popup Menu.}
  929.     procedure SetSeriesVisibility(Value: Boolean);
  930. {Makes series-related menu items visible or otherwise}
  931.     procedure SetSeriesEnabledness(TheMenu: TMenu);
  932. {Makes the Series-related items of an external menu Enabled or otherwise}
  933. {$ENDIF}
  934.  
  935. {Properties that will be published in the non-custom descendant:}
  936.     Property About: string read FAbout write FAbout {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  937. {Displays the "About" dialog box for this component.}
  938.     Property AxesProperties: string read FAxesProperties write FAxesProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  939. {Displays the "Axis Editor" dialog box for the FAxisList subcomponent.}
  940.     Property DataProperties: string read FDataProperties write FDataProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  941. {Displays the "Data Editor" dialog box.}
  942.     Property SeriesProperties: string read FSeriesProperties write FSeriesProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  943.  
  944.     Property AxisList: TList read FAxisList {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  945. {This is a list of all the axes. The 0th is X, the 1st Y.}
  946.  
  947.     Property Bitmap: TBitmap read GetBitmap;
  948. {This returns a Bitmap of the Plot.}
  949. {$IFDEF MSWINDOWS}
  950.     Property Drawing: TMetafile read GetDrawing;
  951.   {This returns a Metafile/Drawing of the Plot.}
  952. {$ENDIF}
  953. {$IFDEF LINUX}
  954.     Property Drawing: TDrawing read GetDrawing;
  955.   {This returns a Metafile/Drawing of the Plot.}
  956. {$ENDIF}
  957. {$IFDEF GIF}
  958.     Property GIF: TGIFImage read GetGIF;
  959. {This returns a Bitmap of the Plot IN GIF FORMAT.}
  960. {$ENDIF}
  961. {$IFDEF PNG}
  962.   {$IFDEF MSWINDOWS}
  963.     Property Png: TPngimage read GetPng;
  964.   {$ENDIF}
  965.   {$IFDEF LINUX}
  966.     Property Png: TBitmap read GetPng;
  967. {This returns a Bitmap of the Plot IN PNG FORMAT.}
  968.   {$ENDIF}
  969. {$ENDIF}
  970.  
  971.     Property PlotPopUpMenu: TPopupMenu read FPlotPopUpMenu;
  972. {The public exposure of the popupmenu for PlotMenu's use.}
  973.     Property Series[Index: Integer]: TSeries read GetSeries {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF}; default;
  974. {This provides direct access to the series maintained by SeriesList.}
  975.     Property SeriesList: TSeriesList read FSeriesList {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  976. {This is the data in a list of data series.}
  977.  
  978.     Property ScreenJob: TScreenJob read FScreenJob write FScreenJob {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  979. {This is the job that is in progress in response to user input.}
  980.  
  981. {Displays the "Series Editor" dialog box.}
  982.     Property Border: TBorder read FBorder write FBorder;
  983. {Manages the geometry of TCustomPlot: where the axes are, where they can go, etc.}
  984.     Property BubbleSize: TPercent read FBubbleSize write SetBubbleSize;
  985. {This is the percentage size of Bubbles, compared to the Y Axis, in the ptBubble PlotType.}
  986.     Property ColumnGap: TPercent read FColumnGap write SetColumnGap;
  987. {This is the percentage gap between groups of Columns in ptColumn PlotType.}
  988.     Property ContourDetail: TContourDetail read FContourDetail write SetContourDetail;
  989. {This is the detail of the colour interpolation in a contour graph.
  990.      cdLow: each triangular tile has uniform colour; this is pretty grainy
  991.      cdMedium: each pixel in each triangular tile has its own colour: this makes a good bitmap, but a lousy metafile
  992.      cdHigh: each rectangular pixel in each triangular tile has its own colour: this makes a good metafile
  993.  See SeriesList.DrawContour.}
  994.     Property Grid: TGridType read FGrid write SetGrid;
  995. {Do we want a grid in XY-type plots ?}
  996.     Property GridStyle: TPenStyle read FGridStyle write SetGridStyle;
  997. {What pen style (dash, dot, etc) do we want for Grids ?}
  998.     Property HelpFile: String read FHelpFile write FHelpFile;
  999. {When this is set to "", TPlot uses Plot.hlp as its context-sensitive help file.}
  1000. {}
  1001. {When set to some other file, it uses that instead.}
  1002.     Property Instructions: TStringList read FInstructions write SetInstructions;
  1003. {This is a message to the user, at the bottom-left of the graph, in the current
  1004.  Font. It disappears on a MouseDown event.}
  1005.  
  1006.     Property ClickAndDragDelay: Integer read GetClickAndDragDelay write SetClickAndDragDelay;
  1007. {The delay (in milliseconds) before a clicked object becomes draggable.}
  1008.  
  1009. {$IFNDEF DELPHI1}
  1010.     Property CreatedBy: String read FCreatedBy write FCreatedBy;
  1011. {A string that is stored in the metafile description.}
  1012. {}
  1013. {This is also used as the "Author" value in a PNG file, if PNG is defined.}
  1014.     Property Description: String read FDescription write FDescription;
  1015. {A string that is stored in the metafile description.}
  1016. {}
  1017. {This is also used as the "Description" value in a PNG file, if PNG is defined.}
  1018. {$ENDIF}
  1019.  
  1020.     Property DisplayHistory: Single read FDisplayHistory write SetHistory;
  1021. {The width of the X Axis when in History mode.}
  1022.     Property DisplayMode: TDisplayMode read FDisplayMode write SetDisplayMode;
  1023. {See TDisplayMode.}
  1024.     Property Editable: Boolean read FEditable write FEditable;
  1025. {Are screen objects like axes Editable ?}
  1026.  
  1027.     Property DefaultExtension: String read FDefaultExtension write SetDefaultExtension;
  1028. {What is the default extension of Plot files ?}
  1029.  
  1030.     Property FileName: String read FFileName write SetFileName {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  1031. {This is the FileName to which the data is saved, or opened from.}
  1032. {}
  1033. {If FileName is blank, and an OpenClick or SaveClick occurs, then the standard
  1034.  file dialog box appears to let the user pick a name.}
  1035.  
  1036.     property HighFont: TFont read FHighFont write FHighFont;
  1037. {The font for annotation of the Highs and Lows.}
  1038. {$IFDEF COMPILER4_UP}
  1039.     property Images: TImageList read GetImages write SetImages; {TCustomImageList}
  1040. {The images for the popupmenu.}
  1041. {$ENDIF}
  1042.     property Legend: TLegend read FLegend write FLegend;
  1043. {The list of series with their line styles. This is a moveable, on-screen object.}
  1044.     property MultiplePen: TPen read FMultiplePen write SetMultiplePen;
  1045. {The pen to use for the verticle lines of ptMultiple PlotTypes (eg: High-Low).}
  1046.     property MultiJoin: String read GetMultiJoin write SetMultiJoin;
  1047. {Which two series, by number, to join with one rectangular symbol, in a ptMultiple plot.
  1048.  Eg: if Multiplicity is 4, and MultiJoin = '2,3', then you have a "Candle" or
  1049.  High-Low-Open-Close plot.}    
  1050.     Property PlotType: TPlotType read FPlotType write SetPlotType;
  1051. {What type of plot is this ?}
  1052.     Property PolarRange: Single read FPolarRange write SetPolarRange;
  1053. {What does 360░ correspond to in a polar graph ? Examples are:
  1054.     2 Pi (6.28...),
  1055.     360 (degrees),
  1056.     60 (minutes),
  1057.     24 (hours)
  1058.     100 (%)
  1059. Get the idea ?    }
  1060.     Property PopupOptions: TPopupOptions read FPopupOptions write SetPopupOptions;
  1061. {If true, then these popup menu items are visible.}
  1062.     Property Movable: Boolean read FMovable write FMovable;
  1063. {Are screen objects like axes movable ?}
  1064.     Property Multiplicity: Byte read FMultiplicity write SetMultiplicity;
  1065. {When the PlotType is ptMultiple, the series are grouped into multiples of Multiplicity.
  1066.  Otherwise ignored.}
  1067.     Property PieRowCount: Byte read FPieRowCount write SetPieRowCount;
  1068. {The number of rows of Pie Graphs.}
  1069.     Property NoSeries: Word read GetNoSeries write SetNoSeries;
  1070. {The number of Series. Setting this can both create new series or free existing series.}
  1071.     Property NoYAxes: Integer read GetNoYAxes write SetNoYAxes;
  1072. {The total number of Y Axes (primary, secondary, tertiary, etc).}    
  1073.     Property PrintOrientation: TPrinterOrientation
  1074.       read FPrintOrientation write FPrintOrientation;
  1075. {Shall we print the graph in Landscape or Portrait mode ?}
  1076.     Property OutlineWidth: Integer read FOutlineWidth write SetOutlineWidth;
  1077. {This is the width of the outline for screen objects like lines: axes and borders.}
  1078.     Property SaveOptions: TSaveOptions read FSaveOptions write FSaveOptions;
  1079. {Shall we save the data as Text or binary ?}
  1080. {}
  1081. {Shall we also save the Plot properties when we save the data ?
  1082.  If we do, then we:
  1083.     1. Save the properties in a seperate file;
  1084.     2. Look for a properties file to open.}
  1085.     Property Title: TTitle read FTitle write FTitle;
  1086. {The title of the graph, including its geometry, font and visibility.}
  1087.     Property XAxis: TAxis read FXAxis write FXAxis;
  1088. {This is the X Axis. Every nice graph should have an X Axis.}
  1089.     Property YAxis: TAxis read FYAxis write FYAxis;
  1090. {This is the Y Axis. Every nice graph should have at least one Y Axis.}
  1091. {}
  1092. {Each Series must know what Y Axes it is being plotted against:
  1093.  Primary (this one) or Secondary.}
  1094.     Property ZAxis: TAngleAxis read FZAxis write FZAxis;
  1095. {This is the Z Axis. Every nice 3D graph should have an Z Axis.}
  1096. {}
  1097. {This is fairly experimental at the moment, so use with caution.
  1098.  It is also nil with non-3D PlotTypes.}
  1099.     Property ZAngle: Word read GetZAngle write SetZAngle;
  1100. {The angle made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  1101.     Property ZLength: Word read GetZLength write SetZLength;
  1102. {The Length made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  1103.     Property ZLink: Boolean read FZLink write SetZLink;
  1104. {Should we link 3D series together in the Z direction ?}
  1105.     Property XYFastAt: Longint read FXYFastAt write SetXYFastAt default 10000;
  1106.     
  1107. {Events:}
  1108.     Property OnAfterPaint: TOnPaintEvent read FOnAfterPaint write FOnAfterPaint;
  1109.     Property OnAfterDraw: TOnPaintEvent read FOnAfterDraw write FOnAfterDraw;
  1110.     Property OnBeforePaint: TOnPaintEvent read FOnBeforePaint write FOnBeforePaint;
  1111.     Property OnBeforeDraw: TOnPaintEvent read FOnBeforeDraw write FOnBeforeDraw;
  1112.  
  1113.     Property OnStyleChange: TNotifyEvent read FOnStyleChange write FOnStyleChange;
  1114.     Property OnDataChange: TNotifyEvent read FOnDataChange write FOnDataChange;
  1115.  
  1116.     Property OnFileOpen: TOnFileEvent read FOnFileOpen write FOnFileOpen;
  1117. {When a file is opened, the app can be notified of the new file name using this event.}
  1118.  
  1119.     Property OnFileClose: TOnFileEvent read FOnFileClose write FOnFileClose;
  1120. {When a file is closed, the app can be notified of the new file name using this event.}
  1121.  
  1122.     Property OnHeader: TOnHeaderEvent read FOnHeader write FOnHeader;
  1123. {When data is opened, this event passes the header information back to the "user".}
  1124.  
  1125.     Property OnHeaderRequest: TOnRequestHeaderEvent read FOnHeaderRequest write FOnHeaderRequest;
  1126. {When data is saved or copied, this event allows the user to add a header
  1127.  to the data.}
  1128.  
  1129.     Property OnHTMLHeaderRequest: TOnRequestHTMLHeaderEvent read FOnHTMLHeaderRequest write FOnHTMLHeaderRequest;
  1130. {When data is copied as HTML, this event allows the user to add a header
  1131.  to the data.}
  1132.  
  1133.     Property OnSelection: TOnSelectionEvent read FOnSelection write SetOnSelection;
  1134. {When the user selects a region, then this event is fired.}
  1135. {}
  1136. {Note that after firing, this event is set to nil, so you have to reset it every usage.}
  1137.     Property OnDualSelection: TOnDualSelectionEvent read FOnDualSelection write SetOnDualSelection;
  1138. {When the user selects TWO regions, then this event is fired.}
  1139. {}
  1140. {Note that after firing, this event is set to nil, so you have to reset it every usage.}
  1141.  
  1142.   public
  1143.     Constructor Create(AOwner: TComponent); override;
  1144. {The usual Constructor, where sub-components are created, properties set, etc.}
  1145.     Destructor Destroy; override;
  1146. {The usual Destructor, where sub-components are destroyed.}
  1147.  
  1148.     procedure Clear(Cancellable: Boolean); virtual;
  1149. {Saves any changed files (at user request) and then clears the SeriesList.}
  1150.  
  1151.     procedure Draw(ACanvas: TCanvas); virtual;
  1152. {This draws the graph on a Canvas. The canvas can be:}
  1153. {}
  1154. {    1. Self.Canvas - ie: on screen;}
  1155. {    2. a Bitmap, for copying and saving.}
  1156. {    3. a MetafileCanvas, for copying and saving.}
  1157. {    4. the printer.}
  1158. {}
  1159. {It is called by Paint, and also many of the copying and saving routines.}
  1160.  
  1161.     function GetFileExtension: String; {csv}
  1162.     function GetFileDriveDir: String;  {D:\Data\Delphi\Plot}
  1163.     function GetFileRoot: String;      {Test3}
  1164.  
  1165.     procedure ShowAbout;
  1166. {This displays the components "About" dialog box.}
  1167.     procedure ShowAxes;
  1168. {This displays the properties of the Series in the SeriesList.}
  1169.     procedure ShowData;
  1170. {This displays the properties of the Data in the DataList.}
  1171.     procedure ShowProperties;
  1172. {This displays the properties of the Plot.}
  1173.     procedure ShowSeries;
  1174. {This displays the properties of the Series in the SeriesList.}
  1175.  
  1176. {Wrappers for the SeriesList functions; the first three also set the
  1177.  OnStyleChange event and the Visibility property:}
  1178.     function AddSeries(XSeriesIndex: Integer): Integer; virtual;
  1179. {This adds a new, empty series to the list.}
  1180.     function AddExternalSeries(XPointer, YPointer: pSingleArray; NumberOfPoints: Integer): Integer; virtual;
  1181. {This adds a new, empty series to the list, and sets its data to point to the
  1182.  external XPointer, YPointer data.}
  1183.     function AddInternalSeries(XPointer, YPointer: pSingleArray; NumberOfPoints: Integer): Integer; virtual;
  1184. {This adds a new, empty series to the list, and copies the data from the
  1185.  XPointer, YPointer data.}
  1186.     function CloneSeries(TheSeries: Integer): Integer; virtual;
  1187. {This adds a new, empty series to the list, copies the data and properties from
  1188.  TheSeries into the new clone, and changes the color and Y Displacement.}
  1189.     procedure DeleteSeries(Index: Integer); virtual;
  1190. {This deletes TheSeries from the list.}
  1191.  
  1192. {$IFNDEF DELPHI1}
  1193.     procedure DetermineMenuEnabledness(TheMenu: TMenu);
  1194. {$ENDIF}
  1195.  
  1196.     procedure AddData(NoPoints: Integer; XYArray: pXYArray); virtual;
  1197. {Add a slice of readings to the internal series.
  1198.  These will become the Nth points in every series.}
  1199. {}
  1200. {This method is extremely useful for data acquisition.}
  1201.  
  1202.     procedure Trace;
  1203. {This draws all the Series in an erasable mode without re-drawing the Axes,
  1204.  Titles or Legend.}
  1205. {}
  1206. {More specifically, the first call to Trace draws the Series, the second erases them.}
  1207. {}
  1208. {This is useful for rapidly changing data such as an oscilloscope. To use it:}
  1209. {}
  1210. {    1. Set up the Axes, etc.}
  1211. {    2. Create each Series you need.}
  1212. {    3a. Use AllocateNoPts for each one, or:}
  1213. {    3b. Allocate and manage the memory yourself, then use PointToData.}
  1214. {    4. Dump you data into each Series via the XData and YData properties.}
  1215. {    5. Trace the data.}
  1216. {    6. Get more data.}
  1217. {    7. Trace the data again to erase the old image.}
  1218. {    8. Repeat steps (4)-(7) indefinitely.}
  1219. {}
  1220. {Note that in step (4), you can either use the XData and YData properties as:}
  1221. {}
  1222. {    a. pSeries.XData^[i];}
  1223. {    b. pX, pY: pSingle; pX := pSeries.XData; pY := pSeries.YData;}
  1224.  
  1225.     procedure CopyClick(Sender: TObject);
  1226. {This responds to a user selection of "Copy" in the popupmenu,
  1227.  and copies the data as text, as a bitmap, and as an enhanced metafile.}
  1228.     procedure HideClick(Sender: TObject);
  1229. {This hides (.Visible := FALSE) the selected object.}
  1230.     procedure PrintClick(Sender: TObject);
  1231. {This prints the graph.}
  1232.     procedure ShowAllClick(Sender: TObject);
  1233. {This shows (.Visible := TRUE) ALL objects.}
  1234.     procedure PositionClick(Sender: TObject);
  1235. {This reports the Position of the mouse (right) click.}
  1236.     procedure NearestPointClick(Sender: TObject);
  1237. {This reports the Position of the nearest data series point to the mouse
  1238.  (right) click.}
  1239.     procedure DeleteSeriesClick(Sender: TObject);
  1240. {This deletes the currently selected series.}
  1241.  
  1242.     procedure CopySeriesClick(Sender: TObject);
  1243. {This copies the selected series to the clipboard in tab-delimited form.}
  1244.     procedure NewSeriesClick(Sender: TObject);
  1245. {This creates a new, empty series.}
  1246.     procedure CloneSeriesClick(Sender: TObject);
  1247. {This creates a new series, and copies the data of the selected series  into it.}
  1248.     procedure ModeClick(Sender: TObject);
  1249.     {procedure ModeNoneClick(Sender: TObject);
  1250.     procedure ModeRunClick(Sender: TObject);
  1251.     procedure ModeHistoryClick(Sender: TObject);}
  1252. {This sets the Display Mode of the graph.}
  1253.     procedure PasteClick(Sender: TObject);
  1254. {This pastes (Tab Delimited) data from the clipboard.}
  1255.     procedure LineBestFitClick(Sender: TObject);
  1256. {This initiates a line of best fit determination.}
  1257.     procedure TwoRegionLineBestFitClick(Sender: TObject);
  1258. {This initiates a line of best fit determination over two different regions.}
  1259. {$IFDEF FUNCTIONS}
  1260.     procedure FunctionClick(Sender: TObject);
  1261. {This creates a new series which is a function of the existing series.}
  1262. {$ENDIF}
  1263.     procedure SmoothSeriesClick(Sender: TObject);
  1264. {This smoothes the currently seleccted data series.}
  1265.     procedure CompressSeriesClick(Sender: TObject);
  1266. {This Compresss the currently selected data series by a factor of 2, 3, 4, etc.}
  1267.     procedure CompressAllSeriesClick(Sender: TObject);
  1268. {This Compresss ALL data series by a factor of 2, 3, 4, etc.}
  1269.     procedure ContractSeriesClick(Sender: TObject);
  1270. {This contracts the currently selected data series by a factor of 2, 3, 4, etc.}
  1271.     procedure ContractAllSeriesClick(Sender: TObject);
  1272. {This contracts ALL data series by a factor of 2, 3, 4, etc.}
  1273.  
  1274.     procedure LegendClick(Sender: TObject);
  1275. {This responds to a user selection of "Legend" in the popupmenu.}
  1276.     procedure EditAxisClick(Sender: TObject);
  1277. {This responds to a user selection of "Axis ..." in the popupmenu,
  1278.  runs the Edit Axis Dialog, and assigns any changes to the appropriate axis.}
  1279.     procedure ApplyAxisChange(Sender: TObject);
  1280. {Apply changes from the AxisEditor to the Axes.}
  1281.     procedure NewNoteClick(Sender: TObject);
  1282. {This responds to a user selection of "New Note ..." in the popupmenu,
  1283.  creates the note, and gets the user to set it and place it.}
  1284.     procedure MoveNotePointerClick(Sender: TObject);
  1285. {This responds to a user selection of "Move Note Pointer" in the popupmenu,
  1286.  and gets the user to move it and place it.}
  1287.     procedure DeleteNoteClick(Sender: TObject);
  1288. {This responds to a user selection of "Delete Note ..." in the popupmenu,
  1289.  checks with the user, then deletes it.}
  1290.     procedure EditFontClick(Sender: TObject);
  1291. {This responds to a user selection of "Font ..." in the popupmenu,
  1292.  runs the FontDialog, and assigns any changes to the appropriate object.}
  1293.     procedure EditPointClick(Sender: TObject);
  1294. {This responds to a user selection of "Point ..." in the popupmenu,
  1295.  runs the Series.PointEdit method, which displays and runs the PointEditor.}
  1296.     procedure EditDataClick(Sender: TObject);
  1297. {This responds to a user selection of "Edit ... Data ..." in the popupmenu,
  1298.  and displays and runs the DataEditor.}
  1299.     procedure EditSeriesClick(Sender: TObject);
  1300. {This responds to a user selection of "Edit ... Series ..." in the popupmenu,
  1301.  and displays and runs the SeriesEditor.}
  1302.     procedure ApplySeriesChange(Sender: TObject);
  1303. {Apply changes from the SeriesEditor to the Series.}
  1304.  
  1305.     procedure ResetDisplacementClick(Sender: TObject);
  1306. {This sets the Displacement properties DeltaX and DeltaY to ZeroScreenStuff.}
  1307.     procedure EditPropertiesClick(Sender: TObject);
  1308. {This responds to a user selection of "Properties ..." in the popupmenu,
  1309.  runs the PropertiesDialog, and assigns any changes to the appropriate objects.}
  1310.     procedure ApplyPropertiesChange(Sender: TObject);
  1311. {This applies changes from the PropertiesDialog.}
  1312.  
  1313.     procedure NewClick(Sender: TObject);
  1314. {This responds to a user selection of "New" in the File popupmenu,
  1315.  and clears all the data and resets the graph.}
  1316.  
  1317.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1318. {needed by D1 for PlotMenu insertion/removal}
  1319.  
  1320.     procedure OpenClick(Sender: TObject);
  1321. {This responds to a user selection of "Open ..." in the popupmenu,
  1322.  runs the Open Dialog, and calls the LoadFromFile method.}
  1323.     procedure OpenFile(TheFile: String);
  1324.  
  1325.     procedure ClearOverlaysClick(Sender: TObject);
  1326. {This responds to a user selection of "Clear Overlays" in the popupmenu,
  1327.  and removes any Overlays.}
  1328.     procedure OverlayClick(Sender: TObject);
  1329. {This responds to a user selection of "Overlay Data" in the popupmenu,
  1330.  runs the Overlay Dialog, and calls the LoadFromFile method.}
  1331.     procedure SaveImageClick(Sender: TObject);
  1332. {This responds to a user selection of "Save Image" in the popupmenu,
  1333.  runs the Save Dialog, and calls the SaveAsBitmap, SaveAsGIF or the SaveAsDrawing method.}
  1334.     procedure SaveClick(Sender: TObject);
  1335. {This responds to a user selection of "Save Data" in the popupmenu,
  1336.  runs the Save Dialog if FileName is blank, and calls the SaveToFile method.}
  1337.     procedure SaveAsClick(Sender: TObject);
  1338. {This responds to a user selection of "Save Data As" in the popupmenu,
  1339.  runs the Save Dialog, and calls the SaveToFile method.}
  1340.     procedure LoadFromFile(AFileName: String); virtual;
  1341. {Loads the data from a file, using LoadFromStream.}
  1342.     procedure LoadFromStream(AStream: TMemoryStream); virtual;
  1343. {Loads the data from a stream.}
  1344.     procedure AppendToFile;
  1345. {Appends the data as text to a text file.}
  1346.     procedure SaveToFile(AFileName: String); virtual;
  1347. {Saves the data as text to a text file, with any TCustomPlot.Owner added header.}
  1348.     procedure SaveToStream(var TheStream: TMemoryStream); virtual;
  1349. {Saves the data to a stream, with any TCustomPlot.Owner added header.}
  1350.  
  1351. {Saving as a picture:}
  1352.     procedure SaveAsBitmap(AFileName: String); virtual;
  1353. {Does what it says.}
  1354.     procedure SaveAsDrawing(AFileName: String); virtual;
  1355. {$IFDEF GIF}
  1356.     procedure SaveAsGIF(AFileName: String); virtual;
  1357. {$ENDIF}
  1358. {Does what it says.}
  1359. {}
  1360. {If GIF is defined (in Plot.inc) then saving as a GIF is enabled.}
  1361. {}
  1362. {Commercial developers note: the use of GIFs requires a license from Unisys:
  1363.  http://www.unisys.com/unisys/lzw/}
  1364.  
  1365. {$IFDEF PNG}
  1366.     procedure SaveAsPNG(AFileName: String); virtual;
  1367. {$ENDIF}
  1368. {Does what it says.}
  1369. {}
  1370. {If PNG is defined (in Plot.inc) then saving as a PNG is enabled.
  1371.  Note that PNG is always enabled under Kylix.}
  1372.  
  1373.     procedure SetAsNormalClick(Sender: TObject);
  1374. {Defines the current view == Mins and Maxes of axes, as the Normal view.}
  1375.     procedure NormalViewClick(Sender: TObject);
  1376. {Zooms the screen the screen to the Normal view.}
  1377.     procedure ManualZoomClick(Sender: TObject);
  1378. {Zooms the screen using a manual dialog box.}
  1379.     procedure ZoomOutClick(Sender: TObject);
  1380. {Zooms the screen out after a zoom-in operation.}
  1381.  
  1382.     procedure MakeDummyData(NoSteps: Integer);
  1383. {This procedure is used to generate some dummy data for testing purposes.}
  1384.  
  1385.     procedure CopyHTMLClick(Sender: TObject);
  1386. {Copies the data as HTML to the Clipboard in CF_TEXT format, with any
  1387.  TCustomPlot.Owner added header.}
  1388.     procedure DisplaceClick(Sender: TObject);
  1389. {This responds to a user selection of "Displace" in the popupmenu, and runs
  1390.  the Displacement Form, which moves the selected Series from its origin.}
  1391.     procedure DifferentiateClick(Sender: TObject);
  1392. {This responds to a user selection of "Differentiate" in the popupmenu,
  1393.  and replaces the selected series with its differential.
  1394. {}
  1395. {(Hint: Clone the series first !)}
  1396.     procedure HandleClick(Sender: TObject; TheTag: Integer);
  1397. {The externally-exposed event handler for all menu items.}
  1398. {}
  1399. {It is used by TPlotMenu to forward the click event to TPlot, which then passes
  1400.  it onto the appropriate handler method based on the value of TheTag.}
  1401.     function GetIndicesFromTag(TheTag: Integer; var i, j: Integer): Boolean;
  1402. {Get the i and j indices for the menu from the Tag.}
  1403.     procedure IntegrateClick(Sender: TObject);
  1404. {This responds to a user selection of "Integrate" in the popupmenu, and replaces
  1405.  the selected series with its integral.}
  1406. {}
  1407. {(Hint: Clone the series first !)}
  1408.     procedure IntegralClick(Sender: TObject);
  1409. {This responds to a user selection of "Integral" in the popupmenu,
  1410.  and calculates the integral of the selected series over the user-selected
  1411.  (by click-and-drag) range.}
  1412.     procedure SortClick(Sender: TObject);
  1413. {This runs the Sort method.}
  1414.     procedure SplineClick(Sender: TObject);
  1415. {This responds to a user menu click and performs a cubic spline interpolation
  1416.  of  the currently selected data series by calling the Spline method.}
  1417.     function Spline(ASeries: Integer): Integer;
  1418. {This performs a cubic spline interpolation of ASeries by calling the
  1419.  TSeries.Spline method to place the cubic spline into a new data series.}
  1420.     procedure ZoomInClick(Sender: TObject);
  1421. {}
  1422.     procedure HighsClick(Sender: TObject);
  1423. {Finds and displays the Highs (peaks) and/or Lows (troughs) of a series.}
  1424.     procedure MovingAverageClick(Sender: TObject);
  1425. {Calculates and displays the Moving Average of a series.}
  1426.     procedure AverageClick(Sender: TObject);
  1427. {Calculates the Average of a series over a range.}
  1428.     procedure LinearizeClick(Sender: TObject);
  1429. {Linearizes a series over a range.}
  1430.     procedure ZeroClick(Sender: TObject);
  1431. {Zeros a series over a range.}
  1432.     procedure NewAxisClick(Sender: TObject);
  1433. {Adds a new axis, based on either the selected or last axis.}    
  1434.     procedure DeleteAxis(Index: Integer; Confirm: Boolean);
  1435. {Deletes the selected axis.}
  1436.     procedure DeleteAxisClick(Sender: TObject);
  1437. {Deletes the axis selected by the user.}
  1438.     procedure SetPlotMenu(Value: TMainMenu);
  1439. {Sets the PlotMenu property.}
  1440.     procedure SetPlotToolBar(Value: TToolBar);
  1441. {Sets the PlotMenu property.}
  1442. {$IFDEF DELPHI4_UP}
  1443.     {procedure SetPlotActionList(Value: TActionList);}
  1444. {Sets the PlotActionList property.}
  1445. {$ENDIF}
  1446.  
  1447.   published
  1448.  
  1449.   end;
  1450. {End of declaration of TCustomPlot.}
  1451.  
  1452. {******************************************************************************}
  1453.   TPlot = class(TCustomPlot)
  1454.   protected
  1455.  
  1456.   public
  1457.     Property AxisList;
  1458. {This is a list of all the axes. The 0th is X, the 1st Y.}
  1459.     Property Bitmap;
  1460. {This returns a Bitmap of the Plot.}
  1461.     Property Drawing;
  1462. {This returns a Drawing/metafile of the Plot. Very useful for printing.}
  1463. {$IFDEF GIF}
  1464.     Property GIF;
  1465. {This returns an image of the Plot IN GIF FORMAT.}
  1466. {$ENDIF}
  1467. {$IFDEF LINUX}
  1468.     Property Png;
  1469. {This returns a Bitmap of the Plot IN PNG FORMAT.}
  1470. {$ENDIF}
  1471.     Property PlotPopUpMenu;
  1472. {The public exposure of the popupmenu for PlotMenu's use.}
  1473.     Property Series;
  1474. {This provides direct access to the series maintained by SeriesList.}
  1475.     Property SeriesList;
  1476. {This is the data in a list of data series.}
  1477.  
  1478.     Property ScreenJob;
  1479. {This is the job that is in progress in response to user input.}
  1480.  
  1481.     Property ZAxis;
  1482. {This is the Z Axis. Every nice 3D graph should have an Z Axis.}
  1483. {}
  1484. {This is fairly experimental at the moment, so use with caution.
  1485.  It is also nil with non-3D PlotTypes.}
  1486.  
  1487.   published
  1488. {All the protected properties of TCustomPlot:}
  1489.     Property About;
  1490. {Displays the "About" dialog box for this component.}
  1491.     Property AxesProperties;
  1492. {Displays the "Axis Editor" dialog box for the FAxisList subcomponent.}
  1493.     Property DataProperties;
  1494. {Displays the "Data Editor" dialog box.}
  1495.     Property SeriesProperties;
  1496. {Displays the "Series Editor" dialog box.}
  1497.     Property Border;
  1498. {Manages the geometry of TCustomPlot: where the axes are, where they can go, etc.}
  1499.     Property ClickAndDragDelay;
  1500. {The delay (in milliseconds) before a clicked object becomes draggable.}
  1501.     Property ColumnGap;
  1502. {This is the percentage gap between groups of Columns in ptColumn PlotType.}
  1503.     Property ContourDetail;
  1504. {This is the detail of the colour interpolation in a contour graph.
  1505.      cdLow: each triangular tile has uniform colour; this is pretty grainy
  1506.      cdMedium: each pixel in each triangular tile has its own colour: this makes a good bitmap, but a lousy metafile
  1507.      cdHigh: each rectangular pixel in each triangular tile has its own colour: this makes a good metafile
  1508.  See SeriesList.DrawContour.}
  1509.  
  1510. {$IFNDEF DELPHI1}
  1511.     Property CreatedBy;
  1512. {For a metafile, this is a string that is stored in the metafile.}
  1513.     Property Description;
  1514. {For a metafile, this is a string that is stored in the metafile.}
  1515. {$ENDIF}
  1516.  
  1517.     Property DisplayHistory;
  1518. {The width of the X Axis when in History mode.}
  1519.     Property DisplayMode;
  1520. {See TDisplayMode.}
  1521.     Property DefaultExtension;
  1522. {What is the default extension of Plot files ?}
  1523.     Property Editable;
  1524. {Are screen objects like axes Editable ?}
  1525.     Property FileName;
  1526. {This is the filename to which the data is saved, or opened from.}
  1527. {}
  1528. {If FileName is blank, and an OpenClick or SaveClick occurs, then the standard
  1529.  file dialog box appears to let the user pick a name.}
  1530.     Property Grid;
  1531. {Do we want a grid in XY-type plots ?}
  1532.     Property GridStyle;
  1533. {What pen style (dash, dot, etc) do we want for Grids ?}
  1534.     property HighFont;
  1535. {The font for annotation of the Highs and Lows.}
  1536.  
  1537. {$IFDEF COMPILER4_UP}
  1538.     property Images;
  1539. {A publication of the Popup Menu's Images property}
  1540. {$ENDIF}
  1541.  
  1542.     Property HelpFile;
  1543. {When this is set to "", TPlot uses Plot.hlp as its context-sensitive help file.}
  1544. {}
  1545. {When set to some other file, it uses that instead.}
  1546.  
  1547.     Property Instructions;
  1548. {This is a hint-like message at the bottom of the graph.
  1549.  It used to be Caption - a string - but now has to be a
  1550.  stringlist to be fully Delphi-compatible (to avoid API calls).
  1551.  Remember Kylix !
  1552.  It disappears upon a MouseDown. See Font.}
  1553.  
  1554.     property Legend;
  1555. {The list of series with their line styles. This is a moveable, on-screen object.}
  1556.     Property Movable;
  1557. {Are screen objects like axes movable ?}
  1558.     Property Multiplicity;
  1559. {When the PlotType is ptMultiple, the series are grouped into multiples of Multiplicity.
  1560.  Otherwise ignored.}
  1561.     property MultiplePen;
  1562. {The pen to use for the verticle lines of ptMultiple PlotTypes (eg: High-Low).}
  1563.     property MultiJoin;
  1564. {Which two series, by number, to join with one rectangular symbol, in a ptMultiple plot.
  1565.  Eg: if Multiplicity is 4, and MultiJoin = '2,3', then you have a "Candle" or
  1566.  High-Low-Open-Close plot.}    
  1567.     property PieRowCount;
  1568. {The number of rows of Pie Graphs.}
  1569.     property NoSeries;
  1570. {The number of Series.}
  1571.     property NoYAxes;
  1572. {The total number of Y Axes (primary, secondary, tertiary, etc).}
  1573.     Property OutlineWidth;
  1574. {This is the width of the outline for screen objects like lines: axes and borders.}
  1575.     Property PlotType;
  1576. {What type of plot is this ?}
  1577.     Property PolarRange;
  1578. {What does 360░ correspond to in a polar graph ? Examples are:
  1579.     2 Pi (6.28...),
  1580.     360 (degrees),
  1581.     60 (minutes),
  1582.     24 (hours)
  1583.     100 (%)
  1584. Get the idea ?    }
  1585.     Property PopupOptions;
  1586. {If true, then these popup menu items are visible.}
  1587.     Property PrintOrientation;
  1588. {Shall we print the graph in Landscape or Portrait mode ?}
  1589.     Property SaveOptions;
  1590. {Shall we save the data as Text or binary ?}
  1591. {}
  1592. {Shall we also save the Plot properties when we save the data ?
  1593.  If we do, then we:
  1594.     1. Save the properties in a seperate file;
  1595.     2. Look for a properties file to open.}
  1596.     Property Title;
  1597. {The title of the graph, including its geometry, font and visibility.}
  1598.     Property XAxis;
  1599. {This is the X Axis. Every nice graph should have an X Axis.}
  1600.     Property YAxis;
  1601. {This is the Y Axis. Every nice graph should have at least one Y Axis.}
  1602. {}
  1603. {Each Series must know what Y Axes it is being plotted against:
  1604.  Primary (this one) or Secondary.}
  1605.     Property ZAngle;
  1606. {The angle made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  1607.     Property ZLink;
  1608. {Should we link 3D series together ?}
  1609.     Property XYFastAt;
  1610.     
  1611. {Events:}
  1612.     Property OnAfterPaint;
  1613.     Property OnAfterDraw;
  1614.     Property OnBeforePaint;
  1615.     Property OnBeforeDraw;
  1616.     Property OnStyleChange;
  1617.     Property OnDataChange;
  1618.  
  1619.     Property OnFileOpen;
  1620. {When a file is opened, the app can be notified of the new file name using this event.}
  1621.  
  1622.     Property OnFileClose;
  1623. {When a file is closed, the app can be notified of the new file name using this event.}
  1624.  
  1625.     Property OnHeader;
  1626. {When data is opened, this event passes the header information back to the "user".}
  1627.  
  1628.     Property OnHeaderRequest;
  1629. {When data is saved or copied, this event allows the user to add a header
  1630.  to the data.}
  1631.  
  1632.     Property OnHTMLHeaderRequest;
  1633. {When data is copied as HTML, this event allows the user to add a header
  1634.  to the data.}
  1635.  
  1636.     Property OnSelection;
  1637.     Property OnDualSelection;
  1638.  
  1639. {all the "extra" TPanel properties in D4 (alias "VCL Bloat"):}
  1640.  
  1641. {Now all the TPanel properties-------------------------------------------------}
  1642. {all the TPanel properties in D1:}
  1643.     property Align;    
  1644.     {property Alignment;}
  1645.     property BevelInner;
  1646.     property BevelOuter;
  1647.     property BevelWidth;
  1648.     property BorderWidth;
  1649.     property BorderStyle;
  1650.     {property Caption; - replaced by Instructions}
  1651.     property Color;
  1652. {$IFDEF MSWINDOWS}
  1653.     property Ctl3D;
  1654.     property DragCursor;
  1655. {$ENDIF}
  1656.     property DragMode;
  1657.     property Enabled;
  1658.     property Font;
  1659. {This is the font of the hint-like message at the bottom of the graph.}
  1660.     property ParentColor;
  1661. {$IFDEF MSWINDOWS}
  1662.     property Locked;
  1663.     property ParentCtl3D;
  1664. {$ENDIF}
  1665.     property ParentFont;
  1666.     property ParentShowHint;
  1667. { Note: D1 to D4 were quite happy for:
  1668.         PopupMenu := FPlotPopUpMenu;
  1669.   FPlotPopUpMenu was then run by inherited MouseUp.
  1670.   However, D5 introduced TControl.WMContextMenu, which ran BEFORE MouseDown.
  1671.   This went spastic when it tried to Popup the PopupMenu.
  1672.  
  1673.   We have therefore returned to hiding FPlotPopUpMenu, and running it manually.
  1674.     property PopupMenu;}
  1675.     property ShowHint;
  1676.     property TabOrder;
  1677.     property TabStop;
  1678.     property Visible;
  1679.     property OnClick;
  1680.     property OnDblClick;
  1681.     property OnDragDrop;
  1682.     property OnDragOver;
  1683.     property OnEndDrag;
  1684.     property OnEnter;
  1685.     property OnExit;
  1686.     property OnMouseDown;
  1687.     property OnMouseMove;
  1688.     property OnMouseUp;
  1689.     property OnResize;
  1690.  
  1691.     
  1692. {$IFDEF COMPILER2_UP}
  1693. {$ENDIF}
  1694.  
  1695. {$IFDEF COMPILER3_UP}
  1696.   {$IFDEF MSWINDOWS}
  1697.     property FullRepaint;
  1698.     property OnStartDrag;
  1699.   {$ENDIF}
  1700. {$ENDIF}
  1701.  
  1702. {$IFDEF COMPILER4_UP}
  1703.     property Anchors;
  1704.     // property AutoSize; - leads to bizzare behaviour
  1705.   {$IFDEF MSWINDOWS}
  1706.     property BiDiMode;
  1707.   {$ENDIF}
  1708.     property Constraints;
  1709.   {$IFDEF MSWINDOWS}
  1710.     property UseDockManager default True;
  1711.     property DockSite;
  1712.     property DragKind;
  1713.     property ParentBiDiMode;
  1714.     property OnCanResize;
  1715.   {$ENDIF}
  1716.     property OnConstrainedResize;
  1717.   {$IFDEF MSWINDOWS}
  1718.     property OnDockDrop;
  1719.     property OnDockOver;
  1720.     property OnEndDock;
  1721.     property OnGetSiteInfo;
  1722.     property OnStartDock;
  1723.     property OnUnDock;
  1724.   {$ENDIF}
  1725. {$ENDIF}
  1726.  
  1727. {$IFDEF COMPILER5_UP}
  1728. {$ENDIF}
  1729.   end;
  1730.  
  1731. {$IFDEF COMPILER3_UP}
  1732. resourcestring
  1733.   CompanyName = 'Chemware';
  1734.   ProductName = 'TPlot';
  1735.   Version = 'Version 2.00';
  1736.   Copyright = 'Copyright ⌐ 1999-2001 Chemware';
  1737. {$ENDIF}
  1738.  
  1739. implementation
  1740. {$IFDEF DELPHI1}
  1741. {$R strlist.res}
  1742. {$R Cursor16.res}
  1743. {$ELSE}
  1744. {$R Strlist32.res}
  1745. {$R Cursor32.res}
  1746. {$ENDIF}
  1747.  
  1748. uses
  1749.   Plotmenu, Plottoolbar;
  1750.  
  1751. {TCustomPlot methods --------------------------------------------------------------}
  1752. {------------------------------------------------------------------------------
  1753.     Procedure: TCustomPlot.ShowAbout
  1754.   Description: Property editor methods, et cetera
  1755.        Author: Mat Ballard
  1756.  Date created: 12/1/1999
  1757. Date modified: 03/29/2001 by Mat Ballard
  1758.       Purpose: design-time user interface
  1759.  Known Issues: TAboutDlg adds about 8 K to the app
  1760.  ------------------------------------------------------------------------------}
  1761. procedure TCustomPlot.ShowAbout;
  1762. var
  1763.   AboutDlg: TAboutDlg;
  1764.   {Msg: String;}
  1765. begin
  1766.   AboutDlg := TAboutDlg.Create(nil);
  1767.   AboutDlg.Comments :=
  1768.     'TPlot version ' + FloatToStrF(TPLOT_VERSION / 100, ffFixed, 5, 2) + #10 +
  1769.     'Released under the Q Public License' + #10 + #10 +
  1770.     'Acknowledgements to' + #10 +
  1771.     '  Anders Melanders - TGifImage' + #10 +
  1772.     '  Edmund H. Hand, Dominique Louis, Uberto Barbini and' + #10 +
  1773.     '    Eric Engler - TPngimage' + #10 +
  1774.     '  Atanas Stoyanov - MemProof' + #10 +
  1775.     '  Renate Schaaf, Alin Flaider, Hallvard Vassbotn and' + #10 +
  1776.     '    Stefan Hoffmeister - TParser10' + #10 +
  1777.     '  John Shemitz - rotated Kylix text';
  1778.     
  1779.   AboutDlg.Execute;
  1780.   AboutDlg.Free;
  1781.   {Msg := 'TPlot version ' + FloatToStrF(TPLOT_VERSION / 100, ffFixed, 5, 2) + #10;
  1782.   Msg := Msg + 'Copyright ⌐ 2000-2001 Mat Ballard' + #10;
  1783.   Msg := Msg + 'e-mail: mat.ballard@chemware.hypermart.net' + #10;
  1784.   Msg := Msg + 'Build date: 15 March 2001';
  1785.   ShowMessage(Msg);}
  1786. end;
  1787.  
  1788. procedure TCustomPlot.ShowData;
  1789. begin
  1790.   EditDataClick(Self);
  1791. end;
  1792.  
  1793. procedure TCustomPlot.ShowSeries;
  1794. begin
  1795.   EditSeriesClick(Self);
  1796. end;
  1797.  
  1798. procedure TCustomPlot.ShowAxes;
  1799. begin
  1800.   EditAxisClick(Self);
  1801. end;
  1802.  
  1803. procedure TCustomPlot.ShowProperties;
  1804. begin
  1805.   EditPropertiesClick(Self);
  1806. end;
  1807.  
  1808. {Constructor and Destructor:-------------------------------------------------}
  1809. {------------------------------------------------------------------------------
  1810.     Procedure: TCustomPlot.Create
  1811.   Description: class constructor
  1812.        Author: Mat Ballard
  1813.  Date created: 12/1/1999
  1814. Date modified: 02/25/2000 by Mat Ballard
  1815.       Purpose: initialize variables and create sub-components
  1816.  Known Issues:
  1817.  ------------------------------------------------------------------------------}
  1818. Constructor TCustomPlot.Create(
  1819.   AOwner:TComponent);
  1820. begin
  1821. {First call the ancestor:}
  1822.   inherited Create(AOwner);
  1823.  
  1824. {we create all objects here, otherwise property changes trigger
  1825.  references to non-existent objects:}
  1826.   FPlotPopUpMenu := TPopupMenu.Create(Self);
  1827. { see note above at 'property PopupMenu':
  1828.   PopUpMenu := FPlotPopUpMenu;}
  1829.   FPopupOptions := TPopupOptions.Create;
  1830.  
  1831.   FInstructions := TStringList.Create;
  1832.  
  1833.   FFlashEdit := nil;
  1834.  
  1835. {create the list of all axes:}
  1836.   FAxisList := TList.Create;
  1837. {create all the Axes:}
  1838.   FXAxis := TAxis.Create(Self);
  1839.   FAxisList.Add(FXAxis);
  1840.   FYAxis := TAxis.Create(Self);
  1841.   FAxisList.Add(FYAxis);
  1842.  
  1843. {create the list of data series:}
  1844.   FSeriesList := TSeriesList.Create(FAxisList);
  1845. {Do things with the series list:}
  1846.  
  1847. {create the border of the graph:}
  1848.   FBorder := TBorder.Create(Self);
  1849.  
  1850. {create the user-clickable edges of the graph (for clicking and dragging):}
  1851.   LeftBorder := TRectangle.Create(Self);
  1852.   TopBorder := TRectangle.Create(Self);
  1853.   RightBorder := TRectangle.Create(Self);
  1854.   BottomBorder := TRectangle.Create(Self);
  1855.  
  1856. {create the graph title:}
  1857.   FTitle := TTitle.Create(Self);
  1858.  
  1859. {The Result of a least-squares fit:}
  1860.   FResult := TCaption.Create(Self);
  1861.  
  1862. {create the plot legend:}
  1863.   FLegend := TLegend.CreateList(Self, FSeriesList);
  1864.  
  1865. {the font for annotation of the highs and lows:}
  1866.   FHighFont := TFont.Create;
  1867.  
  1868.   FMultiplePen := TPen.Create;
  1869.   FMultiJoin1 := 0;
  1870.   FMultiJoin2 := 0;
  1871.  
  1872. {create the object that is clicked and dragged:}
  1873.   Selection := TRectangle.Create(Self);
  1874.  
  1875. {create the list of objects on the screen:}
  1876.   ScreenObjectList := TList.Create;
  1877.  
  1878. {nil out the page buttons:}
  1879.   FPageButtons[0] := nil;
  1880.   FPageButtons[1] := nil;
  1881.   FPageButtons[2] := nil;
  1882.   FPageButtons[3] := nil;
  1883.  
  1884. {This is a typical size:}
  1885.   Height := 300;
  1886.   Width := 400;
  1887. {Users can edit some screen text:}
  1888.   FEditable := TRUE;
  1889. {Users can move screen objects:}
  1890.   FMovable := TRUE;
  1891.  
  1892. {10% of Y Axis maximum bubble size:}
  1893.   FBubbleSize := 10;
  1894.  
  1895. {20% gap between columns:}
  1896.   FColumnGap := 20;
  1897.  
  1898. {Dotted grids are the default:}
  1899.   FGridStyle := psDot;
  1900.  
  1901. {our default help file:}
  1902.   FHelpFile := 'Plot.hlp';
  1903.  
  1904. {only one row of pie graphs:}
  1905.   FPieRowCount := 1;
  1906.  
  1907. {High-Low is the default Multiple plot:}
  1908.   FMultiPlicity := 2;
  1909.  
  1910. {One whole rotation corrsponds to ...}
  1911.   FPolarRange := TWO_PI;
  1912.  
  1913.   FZLink := TRUE;
  1914.   FXYFastAt := 10000;
  1915.  
  1916. {No mouse timer as yet:}
  1917.   MouseTimer := TTimer.Create(Self);
  1918.   MouseTimer.Enabled := FALSE;
  1919.   MouseTimer.OnTimer := MouseTimeOut;
  1920.  
  1921. {no series has been selected yet:}
  1922.   pSeries := nil;
  1923.   TheSeries := -1;
  1924.   ClickedObjectType := soNone;
  1925.  
  1926.   FDisplayHistory := 30;
  1927.   FirstOverlay := -1;
  1928.   FPlotMenu := nil;
  1929.   //FPlotActionList := nil;
  1930.   FPrintOrientation := poLandscape;
  1931. {ZeroScreenStuff everything to do with mice:}
  1932.   FScreenJob := sjNone;
  1933.   FOnSelection := nil;
  1934.   FOnDualSelection := nil;
  1935.   FSaveOptions := [soProperties];
  1936.  
  1937.   DefaultExtension := DEF_EXTENSION;
  1938.   FileExtensions[1] := 'csv';
  1939.   FileExtensions[2] := 'txt';
  1940.   FileExtensions[3] := '*';
  1941.  
  1942.   OpenFilterIndex := 1;
  1943.   SaveFilterIndex := 1;
  1944.   ImageFilterIndex := 1;
  1945.  
  1946.   BevelGap := 1;
  1947.  
  1948. {Take the hint:}
  1949.   FInstructions.Add(sInstruction1);
  1950.   FInstructions.Add(sInstruction2);
  1951.  
  1952. {... and initialize the X-Axis:}
  1953.   FXAxis.Title.Units := sseconds;
  1954.   FXAxis.Tag := Ord(soXAxis);
  1955.   FXAxis.Labels.Tag := Ord(soXAxisLabel);
  1956.   FXAxis.Title.Tag := Ord(soXAxisTitle);
  1957.   FXAxis.TickDirection := orRight;
  1958.  
  1959. {... and initialize the Y-Axis:}
  1960.   FYAxis.Direction := drVertical;
  1961.   FYAxis.TickDirection := orLeft;
  1962.   FYAxis.Title.Orientation := orLeft;
  1963.   FYAxis.Title.Units := smVolts;
  1964.   FYAxis.Title.Caption := sYAxis;
  1965.   FYAxis.Tag := Ord(soYAxis);
  1966.   FYAxis.Labels.Tag := Ord(soYAxisLabel);
  1967.   FYAxis.Title.Tag := Ord(soYAxisTitle);
  1968.  
  1969. {create the border dimensions of the plot:}
  1970.   SetDefaults;
  1971.  
  1972. {Name the user-clickable edges of the graph (for clicking and dragging):}
  1973.   LeftBorder.Name := sLeft + ' ' + sBorder;
  1974.   LeftBorder.Tag := Ord(soLeftBorder);
  1975.   TopBorder.Name := sTop + ' ' + sBorder;
  1976.   TopBorder.Tag := Ord(soTopBorder);
  1977.   RightBorder.Name := sRight + ' ' + sBorder;
  1978.   RightBorder.Tag := Ord(soRightBorder);
  1979.   BottomBorder.Name := sBottom + ' ' + sBorder;
  1980.   BottomBorder.Tag := Ord(soBottomBorder);
  1981.  
  1982. {... and initialize the Plot Title:}
  1983.   FTitle.Caption := ClassName;
  1984.   FTitle.Name := sPlotTitle;
  1985.   FTitle.Orientation := orLeft;
  1986.   FTitle.Font.Size := LARGE_FONT_SIZE;
  1987.   FTitle.Tag := Ord(soTitle);
  1988.  
  1989. {The Result of a least-squares fit:}
  1990.   FResult.Font.Size := SMALL_FONT_SIZE;
  1991. {invisibilize it:}
  1992.   FResult.Top := -100;
  1993.   FResult.Tag := Ord(soResult);
  1994.  
  1995. {... and initialize the plot legend:}
  1996.   FLegend.Name := sLegend;
  1997.   FLegend.Font.Size := SMALL_FONT_SIZE;
  1998.   FLegend.Tag := Ord(soLegend);
  1999.  
  2000. {Initialize the Instruction font:}
  2001.   Font.Name := sArial;
  2002.   Font.Size := SMALL_FONT_SIZE;
  2003.   Font.Color := clRed;
  2004. {the font for annotation of the highs and lows:}
  2005.   FHighFont.Name := sArial;
  2006.   FHighFont.Size := SMALL_FONT_SIZE;
  2007.  
  2008. {load the list of screen objects:}
  2009.   ScreenObjectList.Add(Selection);
  2010.   ScreenObjectList.Add(FTitle);
  2011.   ScreenObjectList.Add(FLegend);
  2012.   ScreenObjectList.Add(FResult);
  2013.   ScreenObjectList.Add(FXAxis);
  2014.   ScreenObjectList.Add(FXAxis.Title);
  2015.   ScreenObjectList.Add(FXAxis.Labels);
  2016.   ScreenObjectList.Add(FYAxis);
  2017.   ScreenObjectList.Add(FYAxis.Title);
  2018.   ScreenObjectList.Add(FYAxis.Labels);
  2019.   ScreenObjectList.Add(LeftBorder);
  2020.   ScreenObjectList.Add(TopBorder);
  2021.   ScreenObjectList.Add(RightBorder);
  2022.   ScreenObjectList.Add(BottomBorder);
  2023. {Note: NoBasicScreenObjects is this list here.
  2024.  Additional objects (secondary Y Axes, Z Axes, notes, etc,
  2025.  are not counted in this total.}
  2026.   NoBasicScreenObjects := ScreenObjectList.Count;
  2027. {The reason for this is that these latter can be added in any order.}
  2028.  
  2029. {create the list of notes:}
  2030.   //NoteList := TList.Create;
  2031.   NoteCount := 0;
  2032.  
  2033.   SetPlotType(ptXY);
  2034.  
  2035. {set the user-clickable border thicknesses:}
  2036.   SetOutlineWidth(10);
  2037. {this fires SetAxisDimensions.}
  2038.  
  2039.   CreateMenus;
  2040.  
  2041. {Set all the OnStyleChanges:}
  2042.   FXAxis.OnChange := DoStyleChange;
  2043.   FYAxis.OnChange := DoStyleChange;
  2044.   FBorder.OnChange := DoStyleChange;
  2045.   FTitle.OnChange := DoStyleChange;
  2046.   FSeriesList.OnStyleChange := DoStyleChange;
  2047.   FSeriesList.OnDataChange := DoDataChange;
  2048.   FLegend.OnChange := DoStyleChange;
  2049.  
  2050.   Color := clWindow;
  2051.  
  2052. {load some cursors:}
  2053. {$IFDEF MSWINDOWS}
  2054.   Screen.Cursors[crScope] := {WinProcs.}LoadCursor(HInstance, 'crScope');
  2055.   Screen.Cursors[crX] := {WinProcs.}LoadCursor(HInstance, 'crX');
  2056. {$ENDIF}
  2057.   ZeroScreenStuff;
  2058.   IgnoreChanges := FALSE;
  2059.   if (csDesigning in ComponentState) then
  2060.     MakeDummyData(20);
  2061. end;
  2062.  
  2063. {functions called by constructor ----------------------------------------------}
  2064. {set the graph dimensions:}
  2065. procedure TCustomPlot.SetDefaults;
  2066. begin
  2067.   FBorder.Left := 70;
  2068.   FBorder.Top := 40;
  2069.   FBorder.RightEx := Width;
  2070.   FBorder.BottomEx := Height;
  2071.   FBorder.RightGap := 50;
  2072.   FBorder.BottomGap := 80;
  2073. end;
  2074.  
  2075. {------------------------------------------------------------------------------
  2076.     Procedure: TCustomPlot.MakeDummyData
  2077.   Description: procedure to add two series, with sine wave data
  2078.        Author: Mat Ballard
  2079.  Date created: 12/1/1999
  2080. Date modified: 02/25/2000 by Mat Ballard
  2081.       Purpose: 1. test TCustomPlot
  2082.                2. display capabilities in design mode.
  2083.  Known Issues:
  2084.  ------------------------------------------------------------------------------}
  2085. procedure TCustomPlot.MakeDummyData(NoSteps: Integer);
  2086. var
  2087.   i,
  2088.   j: Integer;
  2089.   Amplitude,
  2090.   MidY,
  2091.   Phase,
  2092.   StepSize,
  2093.   X,
  2094.   Y: Single;
  2095.   OldIgnoreChanges: Boolean;
  2096. begin
  2097.   OldIgnoreChanges := IgnoreChanges;
  2098.   IgnoreChanges := TRUE;
  2099. {clean up first:}
  2100.   for i := 0 to FSeriesList.Count-1 do
  2101.   begin
  2102.     TSeries(FSeriesList.Items[i]).DelData;
  2103.   end;
  2104.  
  2105.   if (FSeriesList.Count = 0) then
  2106.   begin
  2107.     FSeriesList.Add(-1);
  2108.     //TSeries(FSeriesList.Items[0]).OnStyleChange := DoStyleChange(Self);
  2109.     case FPlotType of
  2110.       ptError:
  2111.         begin
  2112. {add two series:}
  2113.           FSeriesList.Add(-1);
  2114.           //TSeries(FSeriesList.Items[1]).OnStyleChange := DoStyleChange(Self);
  2115.         end;
  2116.       ptContour, pt3DContour, pt3DWire{, pt3DSurface}:
  2117.         begin
  2118.         end;
  2119.       else
  2120.         begin
  2121. {add two series, the second depending on the first:}
  2122. {this second series uses the X data of the first series:}
  2123.           FSeriesList.Add(0);
  2124.           TSeries(FSeriesList.Items[1]).OnStyleChange := DoStyleChange;
  2125.         end;
  2126.     end; {case}
  2127.   end;
  2128.  
  2129. {seed it:}
  2130.   Randomize;
  2131. {set the phase for trig functions:}
  2132.   Phase := Random;
  2133. {initialize: calculate the step size:}
  2134.   StepSize := (FXAxis.Max - FXAxis.Min) / NoSteps;
  2135. {... and the size:}
  2136.   Amplitude := (FYAxis.Max - FYAxis.Min) / 2;
  2137.   MidY := (FYAxis.Max + FYAxis.Min) / 2;
  2138.   for i := 0 to NoSteps do
  2139.   begin
  2140.     for j := 0 to FSeriesList.Count-1 do
  2141.     begin
  2142.       case FPlotType of
  2143.         ptError, ptBubble:
  2144.           begin
  2145.             if (j mod 2 > 0) then
  2146.             begin
  2147.               X := Random;
  2148.               Y := Random;
  2149.             end
  2150.             else
  2151.             begin
  2152.               X := FXAxis.Min + i * StepSize;
  2153.               Y := MidY + Amplitude * Sin(X + (j+1) * Phase) + Random;
  2154.             end;
  2155.           end;
  2156.         ptPolar:
  2157.           begin
  2158.             X := (i / NoSteps) * Self.FPolarRange;
  2159.             Y := FXAxis.Max / 2 + (Amplitude/3) * Sin(X + (j+1) * Phase);
  2160.           end;
  2161.         ptContour, pt3DContour, pt3DWire{, pt3DSurface}:
  2162.           begin
  2163.             X := FXAxis.Min + i * StepSize;
  2164.             Y := Exp(-j / 2.0) * (MidY + Amplitude * Sin(X));
  2165.           end;
  2166.         else
  2167.           begin
  2168.             X := FXAxis.Min + i * StepSize;
  2169.             Y := MidY + Amplitude * Sin(X + (j+1) * Phase) + Random;
  2170.           end;
  2171.       end; {case}
  2172.       TSeries(FSeriesList.Items[j]).ZData := j;
  2173. {Don't fire any events, and don't adjust axes:}
  2174.       TSeries(FSeriesList.Items[j]).AddPoint(X, Y, FALSE, FALSE);
  2175.     end; {for j}
  2176.   end; {for i}
  2177.   for j := 0 to FSeriesList.Count-1 do
  2178.     TSeries(FSeriesList.Items[j]).Visible := TRUE;
  2179.   IgnoreChanges := OldIgnoreChanges;
  2180.   ZoomOutClick(Self);
  2181. end;
  2182.  
  2183. {------------------------------------------------------------------------------
  2184.     Procedure: TCustomPlot.CreateMenus
  2185.   Description: creates popup menus that are accessible by right-click
  2186.        Author: Mat Ballard
  2187.  Date created: 12/1/1999
  2188. Date modified: 04/20/2000 by Mat Ballard
  2189.       Purpose: modularize user-interface code
  2190.  Known Issues: this was a bitch to get right !
  2191.  ------------------------------------------------------------------------------}
  2192. procedure TCustomPlot.CreateMenus;
  2193. var
  2194.   i, j,
  2195.   Index,
  2196. {$IFDEF COMPILER4_UP}
  2197.   ImageIndex,
  2198. {$ENDIF}
  2199. {we now need a ResIndex because of the Kylix.Sysutils.LoadStr bug:}
  2200.   ResIndex: Word;
  2201. {This following is just a dummy matrix of menu items used to create sub-menus,
  2202.  then removed and the menuitems freed.}
  2203.   TempMenu: array [0..Ord(mnuCalc)] of array [0..0] of TMenuItem;
  2204.   TempMenuItem: TMenuItem;
  2205.   StrResCaption,
  2206.   StrResName: String;
  2207.   RightDragItems: array[0..8] of TPoint;
  2208. {$IFDEF MSWINDOWS}
  2209.   lpBuffer: array [0..255] of Char;
  2210. {$ENDIF}
  2211. const
  2212.   NoMenusItems: array [0..Ord(mnuCalc)] of Integer =
  2213.     (Ord(mnuPrint),
  2214.      Ord(mnuEditProperties),
  2215.      Ord(mnuZoomOut),
  2216. {$IFDEF FUNCTIONS}
  2217.      Ord(mnuFunction));
  2218. {$ELSE}
  2219.      Ord(mnuTwoRegionLineOfBestFit));
  2220. {$ENDIF}
  2221.  
  2222. begin
  2223. {create the sub-menus:}
  2224.   Index := 1;
  2225.   ResIndex := 1;
  2226. {$IFDEF LINUX}
  2227.   for i := 1 to 1000 do
  2228.   begin
  2229.     StrResCaption := LoadStr(CAPTION_BASE + ResIndex);
  2230.     if (Length(StrResCaption) > 0) then
  2231.     begin
  2232.       //ShowMessageFmt('I have finally found "%s" at %d', [StrResCaption, CAPTION_BASE + Index]);
  2233.       break;
  2234.     end
  2235.      else
  2236.       Inc(ResIndex);
  2237.   end;
  2238. {$ENDIF}
  2239.  
  2240.   for i := Ord(mnuFile) to Ord(mnuCalc) do
  2241.   begin
  2242. {we create a temporary menu array to add the submenu, and then later remove it:}
  2243.     TempMenu[i][0] := TMenuItem.Create(Self);
  2244. {load the caption from resource:}
  2245. {$IFDEF MSWINDOWS}
  2246.     {WinProcs.}LoadString(HINSTANCE, CAPTION_BASE + ResIndex, lpBuffer, 256);
  2247.     StrResCaption := StrPas(lpBuffer);
  2248. {$ENDIF}
  2249. {$IFDEF LINUX}
  2250.     StrResCaption := LoadStr(CAPTION_BASE + ResIndex);
  2251. {$ENDIF}
  2252.     StrResName := CleanString(StrResCaption, '&');
  2253.     StrResName := CleanString(StrResName, '.');
  2254.     StrResName := CleanString(StrResName, ' ');
  2255.     StrResName := StrResName + 'SubMenu';
  2256.     TempMenuItem := NewSubMenu(
  2257.       StrResCaption,
  2258.       0,
  2259.       StrResName,
  2260.       TempMenu[i]);
  2261.     TempMenuItem.Tag := Index + TAG_BASE;
  2262.     FPlotPopUpMenu.Items.Add(TempMenuItem);
  2263.  
  2264.     Inc(Index);
  2265.     Inc(ResIndex);
  2266.   end;
  2267.  
  2268. {$IFDEF COMPILER4_UP}
  2269.   ImageIndex := 0;
  2270. {$ENDIF}
  2271. {create the menus in each sub-menu:}
  2272.   for i := Ord(mnuFile) to Ord(mnuCalc) do
  2273.   begin
  2274.     for j := 0 to NoMenusItems[i] do
  2275.     begin
  2276. {load the caption from resource:}
  2277. {$IFDEF MSWINDOWS}
  2278.       {WinProcs.}LoadString(HINSTANCE, CAPTION_BASE + ResIndex, lpBuffer, 256);
  2279.       StrResCaption := StrPas(lpBuffer);
  2280. {$ENDIF}
  2281. {$IFDEF LINUX}
  2282.       StrResCaption := LoadStr(CAPTION_BASE + ResIndex);
  2283. {$ENDIF}
  2284.       TempMenuItem := TMenuItem.Create(Self);
  2285.       TempMenuItem.Caption := StrResCaption;
  2286.       TempMenuItem.Tag := Index + TAG_BASE;
  2287.       if (StrResCaption <> '-') then
  2288.       begin
  2289. {$IFDEF COMPILER4_UP}
  2290.         TempMenuItem.ImageIndex := ImageIndex;
  2291.         Inc(ImageIndex);
  2292. {$ENDIF}
  2293.  
  2294. {load the hint from resource}
  2295. {$IFDEF MSWINDOWS}
  2296.         if ({WinProcs.}LoadString(HINSTANCE, HINT_BASE + ResIndex, lpBuffer, 256) > 0) then
  2297.           TempMenuItem.Hint := StrPas(lpBuffer);
  2298. {$ENDIF}
  2299. {$IFDEF LINUX}
  2300.         StrResCaption := LoadStr(HINT_BASE + ResIndex);
  2301.         if (Length(StrResCaption) > 1) then
  2302.           TempMenuItem.Hint := StrResCaption
  2303. {$ENDIF}
  2304.       end; {not a line}
  2305. {add the TempMenuItem to the popup:}
  2306.       FPlotPopUpMenu.Items[i].Add(TempMenuItem);
  2307.  
  2308.       Inc(Index);
  2309.       Inc(ResIndex);
  2310.     end; {j over menu items}
  2311. {remove the temporary menu array used to create the submenu:}
  2312.     if (FPlotPopUpMenu.Items[i].Items[0].Tag = 0) then
  2313.     begin
  2314.       FPlotPopUpMenu.Items[i].Remove(TempMenu[i][0]);
  2315. {then free it:}
  2316.       TempMenu[i][0].Free;
  2317.     end;
  2318.   end; {i over submenus}
  2319.  
  2320. {now set all the OnClick event handlers. what a bitch !}
  2321.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuNew)].OnClick := NewClick;
  2322.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOpen)].OnClick := OpenClick;
  2323.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlayDiv)].OnClick := nil;
  2324.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlay)].OnClick := OverlayClick;
  2325.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuClearOverlays)].OnClick := ClearOverlaysClick;
  2326.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveDiv)].OnClick := nil;
  2327.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSave)].OnClick := SaveClick;
  2328.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveAs)].OnClick := SaveAsClick;
  2329.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveImage)].OnClick := SaveImageClick;
  2330.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrintDiv)].OnClick := nil;
  2331.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrint)].OnClick := PrintClick;
  2332.  
  2333.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopy)].OnClick := CopyClick;
  2334.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].OnClick := CopyHTMLClick;
  2335.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].OnClick := CopySeriesClick;
  2336.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].OnClick := PasteClick;
  2337.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].OnClick := nil;
  2338.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].OnClick := DisplaceClick;
  2339.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].OnClick := ResetDisplacementClick;
  2340.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].OnClick := nil;
  2341.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewSeries)].OnClick := NewSeriesClick;
  2342.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].OnClick := CloneSeriesClick;
  2343.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].OnClick := EditPointClick;
  2344.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].OnClick := EditDataClick;
  2345.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].OnClick := EditSeriesClick;
  2346.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].OnClick := DeleteSeriesClick;
  2347.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].OnClick := LinearizeClick;
  2348.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].OnClick := ZeroClick;
  2349.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuAxisDiv)].OnClick := nil;
  2350.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewY2Axis)].OnClick := NewAxisClick;
  2351.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].OnClick := EditAxisClick;
  2352.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].OnClick := DeleteAxisClick;
  2353.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFontDiv)].OnClick := nil;
  2354.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewNote)].OnClick := NewNoteClick;
  2355.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].OnClick := MoveNotePointerClick;
  2356.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].OnClick := DeleteNoteClick;
  2357.  
  2358.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].OnClick := EditFontClick;
  2359.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPropertiesDiv)].OnClick := nil;
  2360.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditProperties)].OnClick := EditPropertiesClick;
  2361.  
  2362.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].OnClick := HideClick;
  2363.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuShowAll)].OnClick := ShowAllClick;
  2364.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomDiv)].OnClick := nil;
  2365.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuSetAsNormal)].OnClick := SetAsNormalClick;
  2366.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormalView)].OnClick := NormalViewClick;
  2367. {$IFNDEF SHOWALLMENUS}
  2368.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormalView)].Enabled := FALSE;
  2369. {$ENDIF}
  2370.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuManualZoom)].OnClick := ManualZoomClick;
  2371.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomIn)].OnClick := ZoomInClick;
  2372.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomOut)].OnClick := ZoomOutClick;
  2373.  
  2374.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuPosition)].OnClick := PositionClick;
  2375.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].OnClick := NearestPointClick;
  2376.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].OnClick := nil;
  2377.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].OnClick := AverageClick;
  2378.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].OnClick := CompressSeriesClick;
  2379.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].OnClick := CompressAllSeriesClick;
  2380.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].OnClick := ContractSeriesClick;
  2381.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].OnClick := ContractAllSeriesClick;
  2382.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].OnClick := HighsClick;
  2383.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].OnClick := MovingAverageClick;
  2384.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSplineSeries)].OnClick := SplineClick;
  2385.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].OnClick := SmoothSeriesClick;
  2386.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].OnClick := SortClick;
  2387.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].OnClick := nil;
  2388.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].OnClick := DifferentiateClick;
  2389.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].OnClick := IntegrateClick;
  2390.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].OnClick := IntegralClick;
  2391.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].OnClick := nil;
  2392.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].OnClick := LineBestFitClick;
  2393.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].OnClick := TwoRegionLineBestFitClick;
  2394. {$IFDEF FUNCTIONS}
  2395.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].OnClick := nil;
  2396.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].OnClick := FunctionClick;
  2397. {$ENDIF}
  2398.  
  2399.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuDisplayMode)].OnClick := ModeClick;
  2400.  
  2401.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].OnClick := LegendClick;
  2402.  
  2403. {We create the "which" popup menu:}
  2404.   WhichPopUpMenu := TPopUpMenu.Create(Self);
  2405.   for i := 0 to 1 do begin
  2406.     WhichPopUpItems[i] := TMenuItem.Create(Self);
  2407.     WhichPopUpItems[i].Tag := i;
  2408.     WhichPopUpMenu.Items.Add(WhichPopUpItems[i]);
  2409.   end;
  2410. {Note: we set the FInstructions just before we display this popup:}
  2411.   {WhichPopUpItems[0].Caption := 'ClickedObjectType';}
  2412.   {WhichPopUpItems[1].Caption := 'SecondClickedObjectType';}
  2413.   WhichPopUpItems[0].OnClick := MoveTheClickedObjectClick;
  2414.   WhichPopUpItems[1].OnClick := MoveSecondClickedObjectClick;
  2415.  
  2416. {We create the "Right Drag" popup menu:}
  2417.   RightDragItems[0] :=  Point(Ord(mnuView), Ord(mnuZoomIn));
  2418.   RightDragItems[1] :=  Point(Ord(mnuEdit), Ord(mnuLinearize));
  2419.   RightDragItems[2] :=  Point(Ord(mnuEdit), Ord(mnuZero));
  2420.   RightDragItems[3] :=  Point(Ord(mnuCalc), Ord(mnuCalcAverage));
  2421.   RightDragItems[4] :=  Point(Ord(mnuCalc), Ord(mnuContractSeries));
  2422.   RightDragItems[5] :=  Point(Ord(mnuCalc), Ord(mnuContractAllSeries));
  2423.   RightDragItems[6] :=  Point(Ord(mnuCalc), Ord(mnuIntegral));
  2424.   RightDragItems[7] :=  Point(Ord(mnuCalc), Ord(mnuLineOfBestFit));
  2425.   RightDragItems[8] :=  Point(Ord(mnuCalc), Ord(mnuTwoRegionLineOfBestFit));
  2426.  
  2427.   FDragPopUpMenu := TPopupMenu.Create(Self);
  2428.   for i := 0 to 8 do
  2429.   begin
  2430.     TempMenuItem := TMenuItem.Create(Self);
  2431.     TempMenuItem.Caption :=
  2432.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].Caption;
  2433. {$IFDEF COMPILER4_UP}
  2434.     TempMenuItem.ImageIndex :=
  2435.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].ImageIndex;
  2436. {$ENDIF}
  2437.     TempMenuItem.Tag :=
  2438.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].Tag;
  2439.     TempMenuItem.OnClick :=
  2440.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].OnClick;
  2441.     FDragPopUpMenu.Items.Add(TempMenuItem);
  2442.   end;
  2443. end;
  2444.  
  2445. {------------------------------------------------------------------------------
  2446.     Procedure: TCustomPlot.CreatePageButtons
  2447.   Description: creates the Page buttons and assigns their properties
  2448.        Author: Mat Ballard
  2449.  Date created: 04/28/2001
  2450. Date modified: 04/28/2001 by Mat Ballard
  2451.       Purpose: user interface management
  2452.  Known Issues:
  2453.  ------------------------------------------------------------------------------}
  2454. procedure TCustomPlot.CreatePageButtons;
  2455. var
  2456.   i: Integer;
  2457. begin
  2458.   if (FPageButtons[0] = nil) then
  2459.   begin
  2460.     for i := 0 to 3 do
  2461.     begin
  2462.       FPageButtons[i] := TBitmap.Create;
  2463.     end;
  2464.     FPageButtons[0].LoadFromResourceName(HInstance, 'BMLEFT');
  2465.     FPageButtons[1].LoadFromResourceName(HInstance, 'BMRIGHT');
  2466.     FPageButtons[2].LoadFromResourceName(HInstance, 'BMUP');
  2467.     FPageButtons[3].LoadFromResourceName(HInstance, 'BMDOWN');
  2468.   end;
  2469. end;
  2470.  
  2471. {------------------------------------------------------------------------------
  2472.     Procedure: TCustomPlot.DestroyPageButtons
  2473.   Description: frees the Page buttons
  2474.        Author: Mat Ballard
  2475.  Date created: 04/28/2001
  2476. Date modified: 04/28/2001 by Mat Ballard
  2477.       Purpose: user interface management
  2478.  Known Issues:
  2479.  ------------------------------------------------------------------------------}
  2480. procedure TCustomPlot.DestroyPageButtons;
  2481. var
  2482.   i: Integer;
  2483. begin
  2484.   if (FPageButtons[0] <> nil) then
  2485.   begin
  2486.     for i := 0 to 3 do
  2487.     begin
  2488.       FPageButtons[i].Free;
  2489.       FPageButtons[i] := nil;
  2490.     end;
  2491.   end;
  2492. end;
  2493.  
  2494. {------------------------------------------------------------------------------
  2495.     Procedure: TCustomPlot.PageButtonClick
  2496.   Description: changes the ranges of the axes in Zoomed mode
  2497.        Author: Mat Ballard
  2498.  Date created: 04/28/2001
  2499. Date modified: 04/28/2001 by Mat Ballard
  2500.       Purpose: User Interface control of axis ranges and zooming
  2501.  Known Issues:
  2502.  ------------------------------------------------------------------------------}
  2503. procedure TCustomPlot.PageButtonClick(Index: Integer);
  2504. var
  2505.   Gap,
  2506.   OldVar,
  2507.   NewVar,
  2508.   MinMax: Single;
  2509. begin
  2510.   case Index of
  2511.     0: {left}
  2512.       begin
  2513.         Gap := FXAxis.Max - FXAxis.Min;
  2514.         OldVar := FXAxis.Min;
  2515.         NewVar := OldVar - Gap;
  2516.         MinMax := FSeriesList.Xmin;
  2517.         if (NewVar < MinMax) then
  2518.           NewVar := MinMax;
  2519.         FXAxis.Min := NewVar;
  2520.         FXAxis.Max := NewVar + Gap;
  2521.       end;
  2522.     1: {right}
  2523.       begin
  2524.         Gap := FXAxis.Max - FXAxis.Min;
  2525.         OldVar := FXAxis.Max;
  2526.         NewVar := OldVar + Gap;
  2527.         MinMax := FSeriesList.Xmax;
  2528.         if (NewVar > MinMax) then
  2529.           NewVar := MinMax;
  2530.         FXAxis.Max := NewVar;
  2531.         FXAxis.Min := NewVar - Gap;
  2532.       end;
  2533.     2: {up}
  2534.       begin
  2535.         Gap := FYAxis.Max - FYAxis.Min;
  2536.         OldVar := FYAxis.Max;
  2537.         NewVar := OldVar + Gap;
  2538.         MinMax := FSeriesList.Ymax;
  2539.         if (NewVar > MinMax) then
  2540.           NewVar := MinMax;
  2541.         FYAxis.Max := NewVar;
  2542.         FYAxis.Min := NewVar - Gap;
  2543.       end;
  2544.     3: {down}
  2545.       begin
  2546.         Gap := FYAxis.Max - FYAxis.Min;
  2547.         OldVar := FYAxis.Min;
  2548.         NewVar := OldVar - Gap;
  2549.         MinMax := FSeriesList.Ymin;
  2550.         if (NewVar < MinMax) then
  2551.           NewVar := MinMax;
  2552.         FYAxis.Min := NewVar;
  2553.         FYAxis.Max := NewVar + Gap;
  2554.       end;
  2555.   end;
  2556. end;
  2557.  
  2558. {------------------------------------------------------------------------------
  2559.     Procedure: TCustomPlot.Destroy
  2560.   Description: standard destructor
  2561.        Author: Mat Ballard
  2562.  Date created: 12/1/1999
  2563. Date modified: 02/25/2000 by Mat Ballard
  2564.       Purpose: free sub-components
  2565.  Known Issues:
  2566.  ------------------------------------------------------------------------------}
  2567. Destructor TCustomPlot.Destroy;
  2568. var
  2569.   i: Integer;
  2570. begin
  2571. {nil out the events:}
  2572.   FOnStyleChange := nil;
  2573.   FOnFileOpen := nil;
  2574.   FOnFileClose := nil;
  2575.   FOnHeader := nil;
  2576.   FOnHeaderRequest := nil;
  2577.   FOnHTMLHeaderRequest := nil;
  2578.   FOnSelection := nil;
  2579.   FOnDualSelection := nil;
  2580.  
  2581. {Clear the SeriesList, thereby provoking a file save if required:}
  2582.   Clear(FALSE);
  2583.  
  2584.   DestroyPageButtons;
  2585.   
  2586. {Free all the Notes:}
  2587.   for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  2588.     if (TObject(ScreenObjectList.Items[i]) is TNote) then
  2589.       TNote(ScreenObjectList.Items[i]).Free;
  2590.  
  2591. {Free all the Axes:}
  2592.   for i := FAxisList.Count-1 downto 0 do
  2593.     TAxis(FAxisList.Items[i]).Free;
  2594.  
  2595. {Free the lists of objects:}
  2596.   FAxisList.Free;
  2597.   //NoteList.Free;
  2598.   ScreenObjectList.Free;
  2599.   FSeriesList.Free;
  2600.  
  2601. {Free the visual sub-components}
  2602.   FInstructions.Free;
  2603.   FResult.Free;
  2604.   FLegend.Free;
  2605.   FTitle.Free;
  2606.   FBorder.Free;
  2607.  
  2608. {free non-visible screen elements:}
  2609.   LeftBorder.Free;
  2610.   TopBorder.Free;
  2611.   RightBorder.Free;
  2612.   BottomBorder.Free;
  2613.   Selection.Free;
  2614.  
  2615. {Free fonts, pens, etc:}
  2616.   FHighFont.Free;
  2617.   FMultiplePen.Free;
  2618.   MouseTimer.Free;
  2619.  
  2620. {Free menus:}  
  2621.   FPopupOptions.Free;
  2622.   FPlotPopUpMenu.Free;
  2623.   FDragPopUpMenu.Free;
  2624.   WhichPopUpMenu.Free;
  2625.  
  2626. {then call ancestor:}
  2627.   inherited Destroy;
  2628. end;
  2629.  
  2630. {End Constructor and Destructor: ----------------------------------------------}
  2631.  
  2632. {Get functions ----------------------------------------------------------------}
  2633. {------------------------------------------------------------------------------
  2634.      Function: TCustomPlot.GetSeries
  2635.   Description: private property Get function
  2636.        Author: Mat Ballard
  2637.  Date created: 12/1/1999
  2638. Date modified: 02/25/2000 by Mat Ballard
  2639.       Purpose: interface to Series property, which is the default property
  2640.  Known Issues:
  2641.  ------------------------------------------------------------------------------}
  2642. function TCustomPlot.GetSeries(
  2643.   Index: Integer): TSeries;
  2644. begin
  2645.   if ((Index < 0) or (Index >= FSeriesList.Count)) then raise
  2646.     ERangeError.CreateFmt('There is no series %d: valid indices are from 0 to %d',
  2647.       [Index, FSeriesList.Count-1]);
  2648.   GetSeries := TSeries(FSeriesList.Items[Index]);
  2649. end;
  2650.  
  2651. {Set procedures ---------------------------------------------------------------}
  2652. {------------------------------------------------------------------------------
  2653.     Procedure: TCustomPlot.SetAxisDimensions
  2654.   Description: geometry manager
  2655.        Author: Mat Ballard
  2656.  Date created: 12/1/1999
  2657. Date modified: 02/25/2000 by Mat Ballard
  2658.       Purpose: sets up the border, axes and Title position
  2659.  Known Issues:
  2660.  ------------------------------------------------------------------------------}
  2661. procedure TCustomPlot.SetAxisDimensions;
  2662. var
  2663.   i: Integer;
  2664.   TheRect: TRect;
  2665.   pThisYAxis: TAxis;
  2666.   OldIgnoreChanges: Boolean;
  2667. begin
  2668.   OldIgnoreChanges := IgnoreChanges;
  2669.   IgnoreChanges := TRUE;
  2670.  
  2671.   if (FPlotType = ptContour) then
  2672.   begin
  2673.     if (FYAxis.AutoScale) then
  2674.     begin
  2675.       FYAxis.Min := FSeriesList.ZMin;
  2676.       FYAxis.Max := FSeriesList.ZMax;
  2677.     end;
  2678.   end;
  2679.  
  2680. {do the simple bits, where the border sets the axis lengths:}
  2681.   FXAxis.Left := FBorder.Left;
  2682.   FXAxis.Right := FBorder.Right;
  2683.   for i := 1 to FAxisList.Count-1 do
  2684.   begin
  2685.     pThisYAxis := TAxis(FAxisList[i]);
  2686.     if (pThisYAxis.Name = 'Z') then
  2687.     begin
  2688.       pThisYAxis.Left := FBorder.Left;
  2689.       pThisYAxis.Top := FBorder.Bottom;
  2690.     end
  2691.     else
  2692.     begin
  2693.       pThisYAxis.Top := FBorder.Top;
  2694.       pThisYAxis.Bottom := FBorder.Bottom;
  2695.     end;
  2696.   end;
  2697.  
  2698. {Limit the X Axis intercept:}
  2699.   if (FXAxis.Intercept < FYAxis.Min) then
  2700.     FXAxis.Intercept := FYAxis.Min;
  2701.   if (FXAxis.Intercept > FYAxis.Max) then
  2702.     FXAxis.Intercept := FYAxis.Max;
  2703.   if (FXAxis.AutoScale) then
  2704.     if ((FYAxis.Min <= 0) and (0 <= FYAxis.Max)) then
  2705.       FXAxis.Intercept := 0;
  2706.  
  2707. {Limit the Y Axis intercept:}
  2708.   if (FYAxis.Intercept < FXAxis.Min) then
  2709.     FYAxis.Intercept := FXAxis.Min;
  2710.   if (FYAxis.Intercept > FXAxis.Max) then
  2711.     FYAxis.Intercept := FXAxis.Max;
  2712.   if (FYAxis.AutoScale) then
  2713.     if ((FXAxis.Min <= 0) and (0 <= FXAxis.Max)) then
  2714.       FYAxis.Intercept := 0;
  2715.  
  2716. {Limit the secondary Y Axes intercepts:}
  2717.   for i := 2 to FAxisList.Count-1 do
  2718.   begin
  2719.     pThisYAxis := TAxis(FAxisList[i]);
  2720.     if (not pThisYAxis.AutoScale) then {???}
  2721.     begin
  2722.       pThisYAxis.Intercept := FXAxis.Max +
  2723.         (i-2) * Width;
  2724.     end;
  2725.  
  2726.     if (pThisYAxis.AxisType = atTertiary) then
  2727.     begin
  2728.       if (pThisYAxis.Intercept < FXAxis.XofF(1)) then
  2729.         pThisYAxis.Intercept := FXAxis.XofF(1);
  2730.       if (pThisYAxis.Intercept > FXAxis.XofF(Width-2)) then
  2731.         pThisYAxis.Intercept := FXAxis.XofF(Width-2);
  2732.     end
  2733.     else
  2734.     begin
  2735. {and Secondary axis is limited to the borders:}
  2736.       if (pThisYAxis.Intercept < FXAxis.Min) then
  2737.         pThisYAxis.Intercept := FXAxis.Min;
  2738.       if (pThisYAxis.Intercept > FXAxis.Max) then
  2739.         pThisYAxis.Intercept := FXAxis.Max;
  2740.     end;
  2741.   end;
  2742.  
  2743. {Set the screen positions based on the Intercepts:}                            
  2744.   FXAxis.MidY := FYAxis.FofY(FXAxis.Intercept);
  2745.   for i := 1 to FAxisList.Count-1 do
  2746.   begin
  2747.     pThisYAxis := TAxis(FAxisList[i]);
  2748.     if (pThisYAxis.Name <> 'Z') then
  2749.       pThisYAxis.MidX := FXAxis.FofX(pThisYAxis.Intercept);
  2750.   end;
  2751.   
  2752. {do the borders for click-and-drag purposes:}
  2753.   LeftBorder.Top := FBorder.Top;
  2754.   LeftBorder.Bottom := FBorder.Bottom;
  2755.   LeftBorder.MidX := FBorder.Left;
  2756.  
  2757.   RightBorder.Top := FBorder.Top;
  2758.   RightBorder.Bottom := FBorder.Bottom;
  2759.   RightBorder.MidX := FBorder.Right;
  2760.  
  2761.   TopBorder.Left := FBorder.Left;
  2762.   TopBorder.Right := FBorder.Right;
  2763.   TopBorder.MidY := FBorder.Top;
  2764.  
  2765.   BottomBorder.Left := FBorder.Left;
  2766.   BottomBorder.Right := FBorder.Right;
  2767.   BottomBorder.MidY := FBorder.Bottom;
  2768.  
  2769. {set up the title envelope:}
  2770.   TheRect.Left := FBorder.Left;
  2771.   TheRect.Right := FBorder.Right;
  2772.   TheRect.Top := BevelGap + FTitle.Height;
  2773.   TheRect.Bottom := Height - BevelGap - FTitle.Height;
  2774.   FTitle.Envelope := TheRect;
  2775.  
  2776.   IgnoreChanges := OldIgnoreChanges;
  2777. end;
  2778.  
  2779. {------------------------------------------------------------------------------
  2780.     Procedure: TCustomPlot.SetClickAndDragDelay
  2781.   Description: standard property Set procedure
  2782.        Author: Mat Ballard
  2783.  Date created: 04/25/2000
  2784. Date modified: 04/25/2000 by Mat Ballard
  2785.       Purpose: sets the ClickAndDragDelay Property
  2786.  Known Issues:
  2787.  ------------------------------------------------------------------------------}
  2788. procedure TCustomPlot.SetClickAndDragDelay(Value: Integer);
  2789. begin
  2790.   MouseTimer.Interval := Value;
  2791. end;
  2792.  
  2793. {------------------------------------------------------------------------------
  2794.     Procedure: TCustomPlot.SetBubbleSize
  2795.   Description: private property Set procedure
  2796.        Author: Mat Ballard
  2797.  Date created: 12/1/1999
  2798. Date modified: 02/25/2000 by Mat Ballard
  2799.       Purpose: sets the BubbleSize in ptBubble mode
  2800.  Known Issues:
  2801.  ------------------------------------------------------------------------------}
  2802. procedure TCustomPlot.SetBubbleSize(Value: TPercent);
  2803. begin
  2804.   FBubbleSize := Value;
  2805.   DoStyleChange(Self);
  2806. end;
  2807.  
  2808. {------------------------------------------------------------------------------
  2809.     Procedure: TCustomPlot.SetColumnGap
  2810.   Description: private property Set procedure
  2811.        Author: Mat Ballard
  2812.  Date created: 12/1/1999
  2813. Date modified: 02/25/2000 by Mat Ballard
  2814.       Purpose: sets the Gap between Columns in ptColumn mode
  2815.  Known Issues:
  2816.  ------------------------------------------------------------------------------}
  2817. procedure TCustomPlot.SetColumnGap(Value: TPercent);
  2818. begin
  2819.   FColumnGap := Value;
  2820.   DoStyleChange(Self);
  2821. end;
  2822.  
  2823. {------------------------------------------------------------------------------
  2824.     Procedure: TCustomPlot.SetContourDetail
  2825.   Description: private property Set procedure
  2826.        Author: Mat Ballard
  2827.  Date created: 02/08/2001
  2828. Date modified: 02/08/2001 by Mat Ballard
  2829.       Purpose: sets the granularity of the colour interpolation in a contour graph.
  2830.  Known Issues:
  2831.  ------------------------------------------------------------------------------}
  2832. procedure TCustomPlot.SetContourDetail(Value: TContourDetail);
  2833. begin
  2834.   FContourDetail := Value;
  2835.   DoStyleChange(Self);
  2836. end;
  2837.  
  2838. {------------------------------------------------------------------------------
  2839.     Procedure: TCustomPlot.SetDefaultExtension
  2840.   Description: private property Set procedure
  2841.        Author: Mat Ballard
  2842.  Date created: 12/1/1999
  2843. Date modified: 02/25/2000 by Mat Ballard
  2844.       Purpose: sets the DefaultExtension for TPlot files
  2845.  Known Issues:
  2846.  ------------------------------------------------------------------------------}
  2847. procedure TCustomPlot.SetDefaultExtension(
  2848.   Value: String);
  2849. begin
  2850.   FDefaultExtension := Value;
  2851.   FileExtensions[0] := Value;
  2852.   FileTypes :=
  2853.     'Plot Files|*.' + Value
  2854.     + '|Comma Sep Var Files|*.csv'
  2855.     + '|Text Files|*.txt'
  2856.     + '|All Files|*.*';
  2857.   end;
  2858.  
  2859. {------------------------------------------------------------------------------
  2860.     Procedure: TCustomPlot.SetDisplayMode
  2861.   Description: private property Set procedure
  2862.        Author: Mat Ballard
  2863.  Date created: 12/1/1999
  2864. Date modified: 02/25/2000 by Mat Ballard
  2865.       Purpose: sets the DisplayMode property, which is how
  2866.                graphs are updated when more data is Added
  2867.  Known Issues:
  2868.  ------------------------------------------------------------------------------}
  2869. procedure TCustomPlot.SetDisplayMode(
  2870.   Value: TDisplayMode);
  2871. begin
  2872.   if (FDisplayMode = Value) then exit;
  2873.  
  2874.   SetDisplayModeHistory(FDisplayHistory, Value);
  2875. end;
  2876.  
  2877. {------------------------------------------------------------------------------
  2878.     Procedure: TCustomPlot.SetDisplayModeHistory
  2879.   Description: adjusts axes and sets DisplayMode and History properties
  2880.        Author: Mat Ballard
  2881.  Date created: 12/1/1999
  2882. Date modified: 02/25/2000 by Mat Ballard
  2883.       Purpose: DisplayMode and History must be set and the graph updated simultaneously.
  2884.  Known Issues:
  2885.  ------------------------------------------------------------------------------}
  2886. procedure TCustomPlot.SetDisplayModeHistory(
  2887.   HistoryValue: Single;
  2888.   ScalingValue: TDisplayMode);
  2889. begin
  2890.   if (ScalingValue = dmHistory) then
  2891.   begin
  2892. {we are changing to History from normal behaviour,
  2893.  or we are in History mode:}
  2894.     FXAxis.Min := -HistoryValue;
  2895.     FXAxis.Max := 0;
  2896.     FYAxis.Intercept := -HistoryValue;
  2897.   end
  2898.   else if (FDisplayMode = dmHistory) then
  2899.   begin
  2900. {We are changing from History to normal behaviour.
  2901.  We therefore need to reset the X Axis dimensions:}
  2902.     if (ScalingValue = dmRun) then
  2903.       FXAxis.Max := 1.5 * FSeriesList.Xmax
  2904.     else
  2905.       FXAxis.Max := FSeriesList.Xmax;
  2906.     FXAxis.Min := FSeriesList.Xmin;
  2907.     FYAxis.Intercept := FXAxis.Min;
  2908.   end;
  2909.   FDisplayHistory := HistoryValue;
  2910.   FDisplayMode := ScalingValue;
  2911.   DoStyleChange(Self);
  2912. end;
  2913.  
  2914. {------------------------------------------------------------------------------
  2915.     Procedure: TCustomPlot.SetGrid
  2916.   Description: private property Set procedure
  2917.        Author: Mat Ballard
  2918.  Date created: 02/28/2001
  2919. Date modified: 02/28/2001 by Mat Ballard
  2920.       Purpose: do we want a grid in XY-type graphs ?
  2921.  Known Issues:
  2922.  ------------------------------------------------------------------------------}
  2923. procedure TCustomPlot.SetGrid(Value: TGridType);
  2924. begin
  2925.   if (FGrid = Value) then exit;
  2926.  
  2927.   FGrid := Value;
  2928.   DoStyleChange(Self);
  2929. end;
  2930.  
  2931. {------------------------------------------------------------------------------
  2932.     Procedure: TCustomPlot.SetGridStyle
  2933.   Description: private property Set procedure
  2934.        Author: Mat Ballard
  2935.  Date created: 02/28/2001
  2936. Date modified: 02/28/2001 by Mat Ballard
  2937.       Purpose: do we want a grid in XY-type graphs ?
  2938.  Known Issues:
  2939.  ------------------------------------------------------------------------------}
  2940. procedure TCustomPlot.SetGridStyle(Value: TPenStyle);
  2941. begin
  2942.   if (FGridStyle = Value) then exit;
  2943.  
  2944.   FGridStyle := Value;
  2945.   DoStyleChange(Self);
  2946. end;
  2947.  
  2948. {------------------------------------------------------------------------------
  2949.     Procedure: TCustomPlot.SetFileName
  2950.   Description: private property Set procedure
  2951.        Author: Mat Ballard
  2952.  Date created: 12/1/1999
  2953. Date modified: 02/25/2000 by Mat Ballard
  2954.       Purpose: sets and parses the FileName property
  2955.  Known Issues:
  2956.  ------------------------------------------------------------------------------}
  2957. procedure TCustomPlot.SetFileName(
  2958.   Value: String);
  2959. begin
  2960.   if (FFileName = Value) then exit;
  2961.  
  2962.   FFileName := Value;
  2963.   if (Length(FFileName) > 0) then
  2964.   begin
  2965.     PropsFileName := GetFileDriveDir;
  2966.     PropsFileName := PropsFileName + GetFileRoot + '.';
  2967.     PropsFileName := PropsFileName + PROP_EXTENSION;
  2968.   end
  2969.    else
  2970.     PropsFileName := '';
  2971. end;
  2972.  
  2973. {------------------------------------------------------------------------------
  2974.     Functions: TCustomPlot.GetFileXXX
  2975.   Description: gets various file parameters from the name
  2976.        Author: Mat Ballard
  2977.  Date created: 08/10/2000
  2978. Date modified: 08/10/2000 by Mat Ballard
  2979.       Purpose: file management
  2980.  Known Issues:
  2981.  ------------------------------------------------------------------------------}
  2982. function TCustomPlot.GetFileExtension: String; {csv}
  2983. var
  2984.   FileExtension: String;
  2985. begin
  2986.   FileExtension := LowerCase(ExtractFileExt(FFileName));
  2987.   if (Pos('.', FileExtension) = 1) then
  2988.     FileExtension := Copy(FileExtension, 2, Length(FileExtension));
  2989.   GetFileExtension := FileExtension;
  2990. end;
  2991.  
  2992. function TCustomPlot.GetFileDriveDir: String;  {D:\Data\Delphi\Plot}
  2993. var
  2994.   FileDriveDir: String;
  2995. begin
  2996.   FileDriveDir := ExtractFilePath(FFileName);
  2997.   if (Length(FileDriveDir) = 0) then
  2998.     FileDriveDir := GetCurrentDir;
  2999.   GetFileDriveDir := FileDriveDir;
  3000. end;
  3001.  
  3002. function TCustomPlot.GetFileRoot: String;      {Test3}
  3003. var
  3004.   Ext,
  3005.   FileRoot: String;
  3006.   i: Integer;
  3007. begin
  3008.   Ext := GetFileExtension;
  3009.   if (Length(Ext) > 0) then
  3010.   begin
  3011.     FileRoot := ExtractFileName(FFileName);
  3012.     i := Pos(Ext, FileRoot);
  3013.     FileRoot := Copy(FileRoot, 1, i-2);
  3014.   end
  3015.   else
  3016.     FileRoot := FFileName;
  3017.   GetFileRoot := FileRoot;
  3018. end;
  3019.  
  3020. {------------------------------------------------------------------------------
  3021.     Procedure: TCustomPlot.GetFilterIndex
  3022.   Description: gets the file filter index from the extension
  3023.        Author: Mat Ballard
  3024.  Date created: 08/10/2000
  3025. Date modified: 08/10/2000 by Mat Ballard
  3026.       Purpose: file management
  3027.  Known Issues:
  3028.  ------------------------------------------------------------------------------}
  3029. function TCustomPlot.GetFilterIndex(
  3030.   Ext: String): Integer;
  3031. var
  3032.   i: Integer;
  3033. begin
  3034. {the default filterindex is actually '*'}
  3035.   GetFilterIndex := 4;
  3036.   for i := 0 to 3 do
  3037.   begin
  3038.     if (LowerCase(Ext) = FileExtensions[i]) then
  3039.     begin
  3040.       GetFilterIndex := i+1;
  3041.       break;
  3042.     end;
  3043.   end;
  3044. end;
  3045. {------------------------------------------------------------------------------
  3046.     Procedure: TCustomPlot.SetHistory
  3047.   Description: private property Set procedure
  3048.        Author: Mat Ballard
  3049.  Date created: 12/1/1999
  3050. Date modified: 02/25/2000 by Mat Ballard
  3051.       Purpose: sets the History property: which is how far back
  3052.                a History graph goes
  3053.  Known Issues:
  3054.  ------------------------------------------------------------------------------}
  3055. procedure TCustomPlot.SetHistory(
  3056.   Value: Single);
  3057. begin
  3058.   if (FDisplayHistory = Value) then exit;
  3059.  
  3060.   SetDisplayModeHistory(Value, FDisplayMode);
  3061. end;
  3062.  
  3063. {------------------------------------------------------------------------------
  3064.     Procedure: TCustomPlot.SetInstructions
  3065.   Description: private property Set procedure
  3066.        Author: Mat Ballard
  3067.  Date created: 10/09/1999
  3068. Date modified: 10/09/2000 by Mat Ballard
  3069.       Purpose: sets the Instructions property
  3070.  Known Issues: Fixed IDE crash when Instructions set
  3071.  ------------------------------------------------------------------------------}
  3072. procedure TCustomPlot.SetInstructions(Value: TStringList);
  3073. begin
  3074.   if (Value.Count > 0) then
  3075.     FInstructions.Assign(Value)
  3076.    else
  3077.     FInstructions.Clear;
  3078.   DoStyleChange(Self);
  3079. end;
  3080.  
  3081. {$IFDEF COMPILER4_UP}
  3082. {------------------------------------------------------------------------------
  3083.     Procedure: TCustomPlot.SetImages
  3084.   Description: private property Set procedure
  3085.        Author: Mat Ballard
  3086.  Date created: 10/09/1999
  3087. Date modified: 10/09/2000 by Mat Ballard
  3088.       Purpose: sets the Images property
  3089.  Known Issues: TMenu.Images is of type TCustomImageList, which lurks in unit
  3090.                imglist; however, BC++'s DCLSTD35 contains an imglist, and so
  3091.                we get a namespace collision.
  3092.  ------------------------------------------------------------------------------}
  3093. procedure TCustomPlot.SetImages(Value: TImageList);
  3094. begin
  3095.   FPlotPopUpMenu.Images := Value;
  3096.   FDragPopUpMenu.Images := Value;
  3097. end;
  3098.  
  3099. {------------------------------------------------------------------------------
  3100.     Procedure: TCustomPlot.GetImages
  3101.   Description: private property Set procedure
  3102.        Author: Mat Ballard
  3103.  Date created: 10/09/1999
  3104. Date modified: 10/09/2000 by Mat Ballard
  3105.       Purpose: sets the Images property
  3106.  Known Issues: TMenu.Images is of type TCustomImageList, which lurks in unit
  3107.                imglist; however, BC++'s DCLSTD35 contains an imglist, and so
  3108.                we get a namespace collision.
  3109.  ------------------------------------------------------------------------------}
  3110. function TCustomPlot.GetImages: TImageList;
  3111. begin
  3112.   GetImages := TImageList(FPlotPopUpMenu.Images);
  3113. end;
  3114. {$ENDIF}
  3115.  
  3116. {------------------------------------------------------------------------------
  3117.     Procedure: TCustomPlot.SetMetafileDescription
  3118.   Description: sets the CreatedBy and Description properties
  3119.                if they are not yet set
  3120.        Author: Mat Ballard
  3121.  Date created: 12/1/1999
  3122. Date modified: 02/25/2000 by Mat Ballard
  3123.       Purpose: fully utilise enhanced metafile capabilities to
  3124.                put keywords into WMF
  3125.  Known Issues:
  3126.  ------------------------------------------------------------------------------}
  3127. {$IFNDEF DELPHI1}
  3128. procedure TCustomPlot.SetMetafileDescription;
  3129. var
  3130.   i: Integer;
  3131. begin
  3132.   if (Length(FCreatedBy) = 0) then
  3133.     FCreatedBy := 'Chemware';
  3134.   FCreatedBy := InputBox(sCreatedBy1, sCreatedBy2, FCreatedBy);
  3135.  
  3136.   if (Length(FDescription) = 0) then
  3137.   begin
  3138.     FDescription := FTitle.Caption + ': ';
  3139.     for i := 0 to FSeriesList.Count-1 do
  3140.     begin
  3141.       FDescription := FDescription + TSeries(FSeriesList.Items[i]).Name + ', ';
  3142.     end;
  3143. {remove trailing ', ':}    
  3144.     SetLength(FDescription, Length(FDescription)-2);
  3145.   end;
  3146.   FDescription := InputBox('Author', 'Please enter a description', FDescription);
  3147. end;
  3148. {$ENDIF}
  3149.  
  3150. {------------------------------------------------------------------------------
  3151.     Procedure: TCustomPlot.SetMultiplicity
  3152.   Description: standard property Set procedure
  3153.        Author: Mat Ballard
  3154.  Date created: 12/1/1999
  3155. Date modified: 02/25/2000 by Mat Ballard
  3156.       Purpose: sets the Multiplicity property
  3157.  Known Issues: see also: PlotTpe property
  3158.  ------------------------------------------------------------------------------}
  3159. procedure TCustomPlot.SetMultiplicity(Value: Byte);
  3160. begin
  3161.   FMultiplicity := Value;
  3162.   if (FPlotType = ptMultiple) then DoStyleChange(Self);
  3163. end;
  3164.  
  3165. {------------------------------------------------------------------------------
  3166.     Procedure: TCustomPlot.SetMultiplePen
  3167.   Description: standard property Set procedure
  3168.        Author: Mat Ballard
  3169.  Date created: 12/1/1999
  3170. Date modified: 02/25/2000 by Mat Ballard
  3171.       Purpose: sets the Multiplicity property
  3172.  Known Issues: see also: PlotType property
  3173.  ------------------------------------------------------------------------------}
  3174. procedure TCustomPlot.SetMultiplePen(Value: TPen);
  3175. begin
  3176.   FMultiplePen.Assign(Value);
  3177.   if (FPlotType = ptMultiple) then DoStyleChange(Self);
  3178. end;
  3179.  
  3180. {------------------------------------------------------------------------------
  3181.      Function: TCustomPlot.GetMultiJoin
  3182.   Description: standard property Set procedure
  3183.        Author: Mat Ballard
  3184.  Date created: 04/18/2001
  3185. Date modified: 04/18/2001 by Mat Ballard
  3186.       Purpose: sets the MultiJoin property
  3187.  Return Value: String, in the form "x,y"
  3188.  Known Issues: see also: PlotType property
  3189.  ------------------------------------------------------------------------------}
  3190. function TCustomPlot.GetMultiJoin: String;
  3191. begin
  3192.   GetMultiJoin := Format('%d,%d', [FMultiJoin1, FMultiJoin2]);
  3193. end;
  3194.  
  3195. {------------------------------------------------------------------------------
  3196.     Procedure: TCustomPlot.SetMultiJoin
  3197.   Description: standard property Set procedure
  3198.        Author: Mat Ballard
  3199.  Date created: 04/18/2001
  3200. Date modified: 04/18/2001 by Mat Ballard
  3201.       Purpose: sets the MultiJoin property
  3202.  Known Issues: see also: PlotType property
  3203.  ------------------------------------------------------------------------------}
  3204. procedure TCustomPlot.SetMultiJoin(Value: String);
  3205. var
  3206.   TempStr, TheCell: String;
  3207.   Index: Integer;
  3208. begin
  3209.   if (Value = GetMultiJoin) then exit;
  3210.  
  3211.   if (Pos(',', Value) > 0) then
  3212.   begin
  3213.     TempStr := Value;
  3214.     TheCell := GetWord(TempStr, ',');
  3215. {If any of this throws an exception, we know we have a loser:}
  3216.     try
  3217.       Index := StrToInt(TheCell);
  3218.     {if ((Index < 0) or (Index >= FSeriesList.Count)) then}
  3219.       FMultiJoin2 := StrToInt(TempStr);
  3220.       FMultiJoin1 := Index;
  3221.     except
  3222.       ShowMessage(Value + ' is not a valid MultiJoin !' + #10 + #10 +
  3223.         'Try something like "2,3"');
  3224.     end;
  3225.     if (FPlotType = ptMultiple) then DoStyleChange(Self);
  3226.   end;
  3227. end;
  3228.  
  3229. {------------------------------------------------------------------------------
  3230.     Procedure: TCustomPlot.SetPieRowCount
  3231.   Description: standard property Set procedure
  3232.        Author: Mat Ballard
  3233.  Date created: 12/1/1999
  3234. Date modified: 02/25/2000 by Mat Ballard
  3235.       Purpose: sets the PieRowCount property
  3236.  Known Issues:
  3237.  ------------------------------------------------------------------------------}
  3238. procedure TCustomPlot.SetPieRowCount(Value: Byte);
  3239. begin
  3240.   if ((Value > 0) and
  3241.       (Value <= FSeriesList.Count) and
  3242.       (Value <> FPieRowCount)) then
  3243.   begin
  3244.     FPieRowCount := Value;
  3245.     DoStyleChange(Self);
  3246.   end;
  3247. end;
  3248.  
  3249. {------------------------------------------------------------------------------
  3250.     Procedure: TCustomPlot.SetNoSeries
  3251.   Description: standard property Set procedure
  3252.        Author: Mat Ballard
  3253.  Date created: 22/12/2000
  3254. Date modified: 22/12/2000 by Mat Ballard
  3255.       Purpose: sets the NoSeries property
  3256.  Known Issues:
  3257.  ------------------------------------------------------------------------------}
  3258. procedure TCustomPlot.SetNoSeries(Value: Word);
  3259. var
  3260.   i,
  3261.   j: Integer;
  3262. begin
  3263.   if (Value = FSeriesList.Count) then exit;
  3264.  
  3265.   if (Value > FSeriesList.Count) then
  3266.   begin
  3267.     for i := FSeriesList.Count+1 to Value do
  3268.     begin
  3269. {note that the series are added with independent X data:}
  3270.       j := FSeriesList.Add(-1);
  3271.       TSeries(FSeriesList.Items[j]).OnStyleChange := DoStyleChange;
  3272.     end;
  3273.     if (csDesigning in ComponentState) then
  3274.       MakeDummyData(20);
  3275.   end
  3276.   else
  3277.   begin
  3278.     for i := FSeriesList.Count-1 downto Value do
  3279.       DeleteSeries(i);
  3280.   end;
  3281. end;
  3282.  
  3283. {------------------------------------------------------------------------------
  3284.     Procedure: TCustomPlot.SetOutlineWidth
  3285.   Description: standard property Set procedure
  3286.        Author: Mat Ballard
  3287.  Date created: 12/1/1999
  3288. Date modified: 02/25/2000 by Mat Ballard
  3289.       Purpose: sets the OutlineWidth property
  3290.  Known Issues:
  3291.  ------------------------------------------------------------------------------}
  3292. procedure TCustomPlot.SetOutlineWidth(
  3293.   Value: Integer);
  3294. begin
  3295.   if (FOutlineWidth = Value) then exit;
  3296.  
  3297. {Set border widths:}
  3298.   FOutlineWidth := Value;
  3299.   LeftBorder.Height := FOutlineWidth;
  3300.   LeftBorder.Width := FOutlineWidth;
  3301.   TopBorder.Height := FOutlineWidth;
  3302.   TopBorder.Width := FOutlineWidth;
  3303.   RightBorder.Height := FOutlineWidth;
  3304.   RightBorder.Width := FOutlineWidth;
  3305.   BottomBorder.Height := FOutlineWidth;
  3306.   BottomBorder.Width := FOutlineWidth;
  3307.  
  3308. {Set axis widths:}
  3309.   FXAxis.Height := FOutlineWidth;
  3310.   FYAxis.Width := FOutlineWidth;
  3311.  
  3312.   SetAxisDimensions;
  3313. end;
  3314.  
  3315. {------------------------------------------------------------------------------
  3316.     Procedure: TCustomPlot.SetOnSelection
  3317.   Description: standard property Set procedure
  3318.        Author: Mat Ballard
  3319.  Date created: 04/25/2000
  3320. Date modified: 04/25/2000 by Mat Ballard
  3321.       Purpose: sets the OnSelection event
  3322.  Known Issues:
  3323.  ------------------------------------------------------------------------------}
  3324. procedure TCustomPlot.SetOnSelection(Value: TOnSelectionEvent);
  3325. begin
  3326.   FOnSelection := Value;
  3327.   ScreenJob := sjSelection;
  3328. end;
  3329.  
  3330. {------------------------------------------------------------------------------
  3331.     Procedure: TCustomPlot.SetOnDualSelection
  3332.   Description: standard property Set procedure
  3333.        Author: Mat Ballard
  3334.  Date created: 04/25/2000
  3335. Date modified: 04/25/2000 by Mat Ballard
  3336.       Purpose: sets the OnDualSelection event
  3337.  Known Issues:
  3338.  ------------------------------------------------------------------------------}
  3339. procedure TCustomPlot.SetOnDualSelection(Value: TOnDualSelectionEvent);
  3340. begin
  3341.   FOnDualSelection := Value;
  3342.   ScreenJob := sjDualSelection1;
  3343. end;
  3344.  
  3345.  
  3346. {The painting/drawing methods -----------------------------------------------}
  3347. {------------------------------------------------------------------------------
  3348.     Procedure: TCustomPlot.Paint
  3349.   Description: painting the graph
  3350.        Author: Mat Ballard
  3351.  Date created: 12/1/1999
  3352. Date modified: 02/25/2000 by Mat Ballard
  3353.       Purpose: paints the background, border, then draws the graph: NOT called by graphics and printer.
  3354.  Known Issues:
  3355.  ------------------------------------------------------------------------------}
  3356. procedure TCustomPlot.Paint;
  3357. {const
  3358.   Alignments: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER);}
  3359. var
  3360.   iX, iY: Integer;
  3361.   Rect: TRect;
  3362.   TopColor,
  3363.   BottomColor: TColor;
  3364.  
  3365.   procedure AdjustColors(Bevel: TPanelBevel);
  3366.   begin
  3367.     TopColor := clBtnHighlight;
  3368.     if Bevel = bvLowered then TopColor := clBtnShadow;
  3369.     BottomColor := clBtnShadow;
  3370.     if Bevel = bvLowered then BottomColor := clBtnHighlight;
  3371.   end;
  3372.  
  3373. begin
  3374. {$IFDEF DELPHI3_UP}
  3375.   Assert(Canvas <> nil, sPaintError);
  3376. {$ENDIF}
  3377.  
  3378.   if Assigned(FOnBeforePaint) then
  3379.     OnBeforePaint(Self, Canvas);
  3380.  
  3381.   Canvas.Pen.Mode := pmCopy;
  3382.   Canvas.Pen.Style := psSolid;
  3383.  
  3384.   BevelGap := 0;
  3385.   Rect := GetClientRect;
  3386.   if BevelOuter <> bvNone then
  3387.   begin
  3388.     Inc(BevelGap);
  3389.     AdjustColors(BevelOuter);
  3390.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  3391.   end;
  3392.  
  3393.   Frame3D(Canvas, Rect, Color, Color, BorderWidth);
  3394.  
  3395.   if BevelInner <> bvNone then
  3396.   begin
  3397.     Inc(BevelGap);
  3398.     AdjustColors(BevelInner);
  3399.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  3400.   end;
  3401.   BevelGap := BevelGap * BevelWidth;
  3402.  
  3403.   with Canvas do
  3404.   begin
  3405.     Brush.Color := Color;
  3406.     FillRect(Rect);
  3407.     Brush.Style := bsClear;
  3408.   end;
  3409.  
  3410.   Draw(Canvas);
  3411.  
  3412.   with Canvas do
  3413.   begin
  3414.     Brush.Color := Color;
  3415.     Brush.Style := bsClear;
  3416.   end;
  3417. {The Instructions are usually an instruction to the user.
  3418.  As such, it does not need to be copied or printed,
  3419.  so it is placed here, rather than in the "Draw" method:}
  3420.   DrawInstructions;
  3421.  
  3422.   if (FPageButtons[0] <> nil) then
  3423.   begin
  3424. {Right:}
  3425.     iX := Self.Width - FPageButtons[1].Width - 1;
  3426.     iY := Self.Height - FPageButtons[1].Height - 1;
  3427.     Canvas.Draw(iX, iY, FPageButtons[1]);
  3428. {Down}
  3429.     iX := iX - FPageButtons[3].Width;
  3430.     Canvas.Draw(iX, iY, FPageButtons[3]);
  3431. {Up}
  3432.     Canvas.Draw(iX, iY - FPageButtons[2].Height, FPageButtons[2]);
  3433. {Left}
  3434.     iX := iX - FPageButtons[0].Width;
  3435.     Canvas.Draw(iX, iY, FPageButtons[0]);
  3436.   end;
  3437.  
  3438.  
  3439.   if Assigned(FOnAfterPaint) then
  3440.     OnAfterPaint(Self, Canvas);
  3441. end;
  3442.  
  3443. {------------------------------------------------------------------------------
  3444.     Procedure: TCustomPlot.DrawInstructions
  3445.   Description: draws the instructions
  3446.        Author: Mat Ballard
  3447.  Date created: 12/1/1999
  3448. Date modified: 02/25/2000 by Mat Ballard
  3449.       Purpose: tell the user what to do
  3450.  Known Issues:
  3451.  ------------------------------------------------------------------------------}
  3452. procedure TCustomPlot.DrawInstructions;
  3453. var
  3454.   FontHeight,
  3455.   iX,
  3456.   iY,
  3457.   i: Integer;
  3458. {$IFDEF LINUX}
  3459.   //ARect: TRect;
  3460. {$ENDIF}       
  3461. begin
  3462. {The Instructions are usually an instruction to the user.
  3463.  As such, it does not need to be copied or printed,
  3464.  so it is placed here, rather than in the "Draw" method:}
  3465.   if (FInstructions.Count > 0) then
  3466.   begin
  3467.     Canvas.Font.Assign(Font);
  3468.     FontHeight := Canvas.TextHeight('Wp');
  3469. {Adjust the Position appropriately:}
  3470.     iX := BevelGap + 5;
  3471.     iY := Height - BevelGap - FontHeight;
  3472. {how many lines ?}
  3473.     for i := FInstructions.Count-1 downto 0 do
  3474.     begin
  3475. {Output the text:}
  3476. {$IFDEF MSWINDOWS}
  3477.       Canvas.TextOut(iX, iY, FInstructions[i]);
  3478. {$ENDIF}
  3479. {$IFDEF LINUX}
  3480.       Canvas.TextOut(iX, iY{ + Abs(Canvas.Font.Height)}, FInstructions[i]);
  3481.       //Canvas.TextRect(ARect, iX, iY, FInstructions[i], TOPLEFT_ALIGN);
  3482. {$ENDIF}
  3483.       Dec(iY, FontHeight);
  3484.     end;
  3485.   end;
  3486. end;
  3487.  
  3488. {------------------------------------------------------------------------------
  3489.     Procedure: TCustomPlot.Draw
  3490.   Description: painting the graph
  3491.        Author: Mat Ballard
  3492.  Date created: 12/1/1999
  3493. Date modified: 02/25/2000 by Mat Ballard
  3494.       Purpose: draws the graph on a canvas: graphics and printers call this procedure directly
  3495.  Known Issues:
  3496.  ------------------------------------------------------------------------------}
  3497. procedure TCustomPlot.Draw(
  3498.   ACanvas: TCanvas);
  3499. var
  3500.   FontHeight,
  3501.   FontWidth,
  3502.   i,
  3503.   iX,
  3504.   iY,
  3505.   SeriesIncrement: Integer;
  3506.   OldIgnoreChanges: Boolean;
  3507. {$IFDEF LINUX}
  3508.   //ARect: TRect;
  3509. {$ENDIF}
  3510. begin
  3511. {$IFDEF DELPHI3_UP}
  3512.   Assert(ACanvas <> nil, sDrawError);
  3513. {$ENDIF}
  3514.   if Assigned(FOnBeforeDraw) then
  3515.     OnBeforeDraw(Self, ACanvas);
  3516.  
  3517.   OldIgnoreChanges := IgnoreChanges;
  3518.   IgnoreChanges := TRUE;
  3519.  
  3520.   FTitle.Draw(ACanvas);
  3521.  
  3522.   if (FResult.Visible) and (Length(FResult.Caption) > 0) then
  3523.   begin
  3524.     ACanvas.Font.Assign(FResult.Font);
  3525.     FontHeight := Abs(ACanvas.Font.Height);
  3526.     FontWidth := ACanvas.TextWidth(FResult.Caption);
  3527. {calculate the caption dimensions:}
  3528.     {FResult.Top := Selection.Top;
  3529.     FResult.Left := Selection.Left;}
  3530.     FResult.Right := FResult.Left + FontWidth;
  3531.     FResult.Bottom := FResult.Top + FontHeight;
  3532. {output text to screen:}
  3533. {$IFDEF MSWINDOWS}
  3534.     ACanvas.TextOut(FResult.Left, FResult.Top, FResult.Caption);
  3535. {$ENDIF}
  3536. {$IFDEF LINUX}
  3537.     ACanvas.TextOut(FResult.Left, FResult.Top {+ Abs(Canvas.Font.Height)}, FResult.Caption);
  3538.     //ACanvas.TextRect(ARect, FResult.Left, FResult.Top, FResult.Caption, TOPLEFT_ALIGN);
  3539. {$ENDIF}
  3540. {now draw the line itself:}
  3541. {Y = Intercept + Slope * X  <=> X = (Y - Intercept) / Slope}
  3542.     ACanvas.Pen.Style := psDot;
  3543.     ACanvas.Pen.Color := Font.Color;
  3544.     iX := FXAxis.FofX(XAxis.Min);
  3545.     iY := FYAxis.FofY(Intercept + Slope * XAxis.Min);
  3546.     if (iY < Border.Top) then
  3547.     begin
  3548.       iY := Border.Top;
  3549.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3550.     end
  3551.     else if (iY > Border.Bottom) then
  3552.     begin
  3553.       iY := Border.Bottom;
  3554.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3555.     end;
  3556.     ACanvas.MoveTo(iX, iY);
  3557.     iX := FXAxis.FofX(XAxis.Max);
  3558.     iY := FYAxis.FofY(Intercept + Slope * XAxis.Max);
  3559.     if (iY < Border.Top) then
  3560.     begin
  3561.       iY := Border.Top;
  3562.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3563.     end
  3564.     else if (iY > Border.Bottom) then
  3565.     begin
  3566.       iY := Border.Bottom;
  3567.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3568.     end;
  3569.     Canvas.LineTo(iX, iY);
  3570.   end; {Result Visible}
  3571.  
  3572.   if (FGrid > gtNone) then
  3573.     if (FPlotType <= ptMultiple) then
  3574.       DrawGrid(ACanvas);
  3575.  
  3576.   for i := 0 to FAxisList.Count-1 do
  3577.     TAxis(FAxisList[i]).Draw(ACanvas);
  3578.  
  3579.   if ((FPlotType = ptError) or
  3580.       (FPlotType = ptBubble)) then
  3581.     SeriesIncrement := 2
  3582.    else
  3583.     SeriesIncrement := 1;
  3584.   FLegend.Draw(ACanvas, SeriesIncrement);
  3585.  
  3586.   ACanvas.Font.Assign(FHighFont);
  3587.   case FPlotType of
  3588.     ptXY:
  3589.       begin
  3590.         if (FDisplayMode < dmHistory) then
  3591.           FSeriesList.Draw(ACanvas, FXYFastAt)
  3592.          else
  3593.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);
  3594.       end;
  3595.     ptError:
  3596.       begin
  3597.         if (FDisplayMode < dmHistory) then
  3598.           FSeriesList.DrawError(ACanvas);
  3599.       end;
  3600.     ptMultiple:
  3601.       begin
  3602.         if (FDisplayMode < dmHistory) then
  3603.         begin
  3604.           FSeriesList.DrawMultiple(ACanvas, FMultiplicity, FMultiplePen, FMultiJoin1, FMultiJoin2);
  3605.         end
  3606.         else
  3607.         begin
  3608.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);
  3609.           ACanvas.Pen.Assign(FMultiplePen);
  3610.           FSeriesList.DrawHistoryMultiple(ACanvas, FMultiplicity);
  3611.         end;
  3612.       end;
  3613.     ptBubble:
  3614.       begin
  3615.         if (FDisplayMode < dmHistory) then
  3616.           FSeriesList.DrawBubble(ACanvas, FBubbleSize);
  3617.          {else
  3618.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3619.       end;
  3620.     ptColumn:
  3621.       begin
  3622.         if (FDisplayMode < dmHistory) then
  3623.           FSeriesList.DrawColumns(ACanvas, FColumnGap);
  3624.          {else
  3625.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3626.       end;
  3627.     ptStack:
  3628.         if (FDisplayMode < dmHistory) then
  3629.           FSeriesList.DrawStack(ACanvas, FColumnGap);
  3630.          {else
  3631.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3632.     ptNormStack:
  3633.         if (FDisplayMode < dmHistory) then
  3634.           FSeriesList.DrawNormStack(ACanvas, FColumnGap);
  3635.          {else
  3636.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3637.     ptPie:
  3638.         if (FDisplayMode < dmHistory) then
  3639.         begin
  3640.           FSeriesList.DrawPie(ACanvas, FBorder, FPieRowCount);
  3641.         end;
  3642.          {else
  3643.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3644.     ptPolar:
  3645.         if (FDisplayMode < dmHistory) then
  3646.           FSeriesList.DrawPolar(ACanvas, FPolarRange);
  3647.          {else
  3648.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3649.     ptContour:
  3650.       begin
  3651.         if (FDisplayMode < dmHistory) then
  3652.           FSeriesList.DrawContour(ACanvas, FContourDetail);
  3653.         //DrawContourColors(ACanvas);
  3654.       end;
  3655.     pt3DContour:
  3656.       begin
  3657.         if (FDisplayMode < dmHistory) then
  3658.           FSeriesList.Draw3DContour(ACanvas, FZAxis, FContourDetail);
  3659.         //DrawContourColors(ACanvas);
  3660.       end;
  3661.     pt3DWire:
  3662.       begin
  3663.         if (FDisplayMode < dmHistory) then
  3664.           FSeriesList.Draw3DWire(ACanvas, FZAxis, FZLink);
  3665.       end;
  3666.     {pt3DSurface:
  3667.       begin
  3668.         if (FDisplayMode < dmHistory) then
  3669.           FSeriesList.Draw3DSurface(ACanvas, FZAxis);
  3670.       end;}
  3671.   end;
  3672.  
  3673.   for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  3674.   begin
  3675.     if (TObject(ScreenObjectList.Items[i]) is TNote) then
  3676.       TNote(ScreenObjectList.Items[i]).Draw(ACanvas);
  3677.   end;
  3678.  
  3679.  
  3680.   if Assigned(FOnAfterDraw) then
  3681.     OnAfterDraw(Self, ACanvas);
  3682.  
  3683.   IgnoreChanges := OldIgnoreChanges;
  3684. end;
  3685.  
  3686. {------------------------------------------------------------------------------
  3687.     Procedure: TCustomPlot.DrawGrid
  3688.   Description: painting the graph
  3689.        Author: Mat Ballard
  3690.  Date created: 12/1/1999
  3691. Date modified: 02/25/2000 by Mat Ballard
  3692.       Purpose: draws the grid for xy-type plots
  3693.      Comments:  
  3694.  Known Issues:
  3695.  ------------------------------------------------------------------------------}
  3696. procedure TCustomPlot.DrawGrid(
  3697.   ACanvas: TCanvas);
  3698. var
  3699.   iX, iY: Integer;
  3700.   X, Y: Single;
  3701. begin
  3702.   if (ColorToRGB(Self.Color) = ColorToRGB(clGray)) then
  3703.     ACanvas.Pen.Color := clWhite
  3704.    else
  3705.     ACanvas.Pen.Color := clGray;
  3706.   ACanvas.Pen.Width := 1;
  3707.   ACanvas.Pen.Style := FGridStyle;
  3708.  
  3709. {do the verticals:}
  3710.   if (FGrid > gtHorizontal) then
  3711.   begin
  3712.     X := FXAxis.StepStart;
  3713.     while (X < FXAxis.Max) do
  3714.     begin
  3715.       iX := FXAxis.FofX(X);
  3716.       if (iX <> FYAxis.MidX) then
  3717.       begin
  3718.         ACanvas.MoveTo(iX, FYAxis.Bottom);
  3719.         ACanvas.LineTo(iX, FYAxis.Top);
  3720.       end;
  3721.       X := FXAxis.GetNextXValue(X);
  3722.     end;
  3723.   end;
  3724.  
  3725. {do the horizontals:}
  3726.   if ((FGrid = gtHorizontal) or (FGrid = gtBoth)) then
  3727.   begin
  3728.     Y := FYAxis.StepStart;
  3729.     while (Y < FYAxis.Max) do
  3730.     begin
  3731.       iY := FYAxis.FofY(Y);
  3732.       if (iY <> FXAxis.MidY) then
  3733.       begin
  3734.         ACanvas.MoveTo(FXAxis.Left, iY);
  3735.         ACanvas.LineTo(FXAxis.Right, iY);
  3736.       end;
  3737.       Y := FYAxis.GetNextXValue(Y);
  3738.     end;
  3739.   end;  
  3740. end;
  3741.  
  3742. {------------------------------------------------------------------------------
  3743.     Procedure: TCustomPlot.DrawContourColors
  3744.   Description: painting the graph
  3745.        Author: Mat Ballard
  3746.  Date created: 12/1/1999
  3747. Date modified: 02/25/2000 by Mat Ballard
  3748.       Purpose: draws the scale of colours for a contour plot
  3749.      Comments:  
  3750.  Known Issues:
  3751.  ------------------------------------------------------------------------------}
  3752. procedure TCustomPlot.DrawContourColors(
  3753.   ACanvas: TCanvas);
  3754. var
  3755.   iX, iXp1, iY: Integer;
  3756. begin
  3757.   iX := FBorder.Right + FBorder.RightGap div 5;
  3758.   iXp1 := FBorder.Right + FBorder.RightGap div 3;
  3759.   for iY := FBorder.Bottom downto FBorder.Top do
  3760.   begin
  3761.     ACanvas.Pen.Color := Rainbow((FBorder.Bottom - iY) / (FBorder.Bottom - FBorder.Top));
  3762.     ACanvas.MoveTo(iX, iY);
  3763.     ACanvas.LineTo(iXp1, iY);
  3764.   end;
  3765. end;
  3766.  
  3767. {------------------------------------------------------------------------------
  3768.     Procedure: TCustomPlot.Trace
  3769.   Description: This traces all series: useful for Oscilloscopes
  3770.        Author: Mat Ballard
  3771.  Date created: 02/25/2000
  3772. Date modified: 02/25/2000 by Mat Ballard
  3773.       Purpose: Draws all Series in erasable mode
  3774.  Known Issues:
  3775.  ------------------------------------------------------------------------------}
  3776. procedure TCustomPlot.Trace;
  3777. var
  3778.   i: Integer;
  3779. begin
  3780. {$IFDEF DELPHI3_UP}
  3781.   Assert(Canvas <> nil, sTraceError);
  3782. {$ENDIF}
  3783.  
  3784.   for i := 0 to FSeriesList.Count-1 do
  3785.   begin
  3786.     TSeries(FSeriesList.Items[i]).Trace(Canvas);
  3787.   end;
  3788. end;
  3789.  
  3790. {------------------------------------------------------------------------------
  3791.     Procedure: TCustomPlot.Resize
  3792.   Description: overrides ancestor's ReSize
  3793.        Author: Mat Ballard
  3794.  Date created: 12/1/1999
  3795. Date modified: 02/25/2000 by Mat Ballard
  3796.       Purpose: responds to a resize of the Plot
  3797.  Known Issues:
  3798.  ------------------------------------------------------------------------------}
  3799.  
  3800. procedure TCustomPlot.Resize;
  3801. var
  3802.   OldIgnoreChanges: Boolean;
  3803. begin
  3804.   OldIgnoreChanges := IgnoreChanges;
  3805.   IgnoreChanges := TRUE;
  3806.   FBorder.RightEx := Width;
  3807.   FBorder.BottomEx := Height;
  3808.   IgnoreChanges := OldIgnoreChanges;
  3809.   SetAxisDimensions;
  3810.   //DoStyleChange(Self);
  3811.   inherited Resize;
  3812. end;
  3813.  
  3814. {------------------------------------------------------------------------------
  3815.     Procedure: TCustomPlot.StyleChange
  3816.   Description: target of all of the sub-component OnStyleChange events
  3817.        Author: Mat Ballard
  3818.  Date created: 12/1/1999
  3819. Date modified: 02/25/2000 by Mat Ballard
  3820.       Purpose: responds to changes in sub-components
  3821.  Known Issues: get up to 3 screen re-draws
  3822.  ------------------------------------------------------------------------------}
  3823. {procedure TCustomPlot.StyleChange(
  3824.   Sender: TObject);
  3825. begin
  3826.   if (IgnoreChanges) then exit;
  3827.  
  3828.   SetAxisDimensions;
  3829.   DoStyleChange(Self);
  3830. end;}
  3831.  
  3832. {------------------------------------------------------------------------------
  3833.     Procedure: TCustomPlot.DataChange
  3834.   Description: target of TSeriesList (TSeries) OnDataChange event
  3835.        Author: Mat Ballard
  3836.  Date created: 03/07/2001
  3837. Date modified: 03/07/2001 by Mat Ballard
  3838.       Purpose: responds to changes in sub-components
  3839.  Known Issues:
  3840.  ------------------------------------------------------------------------------}
  3841. {procedure TCustomPlot.DataChange(
  3842.   Sender: TObject);
  3843. begin
  3844.   if (IgnoreChanges) then exit;
  3845.  
  3846.   DoDataChange;
  3847. end;}
  3848.  
  3849. {Mousey stuff -----------------------------------------------------------------}
  3850.  
  3851. {------------------------------------------------------------------------------
  3852.     Procedure: TCustomPlot.DblClick
  3853.   Description: overrides ancestor's DblClick
  3854.        Author: Mat Ballard
  3855.  Date created: 12/1/1999
  3856. Date modified: 02/25/2000 by Mat Ballard
  3857.       Purpose: activates in-place editing of titles
  3858.  Known Issues:
  3859.  ------------------------------------------------------------------------------}
  3860. procedure TCustomPlot.DblClick;
  3861. var
  3862.   i: Integer;
  3863.   TheRect: TRect;
  3864.   TheCaption: TCaption;
  3865.   TheRight: Integer;
  3866. begin
  3867. {get rid of the mouse moving timer:}
  3868.   MouseTimer.Enabled := FALSE;
  3869.  
  3870.   if (FEditable) then
  3871.   begin
  3872.     if ((ClickedObjectType = soTitle) or
  3873.         (ClickedObjectType = soXAxisTitle) or
  3874.         (ClickedObjectType = soYAxisTitle) or
  3875.         (ClickedObjectType = soNote)) then
  3876.     begin
  3877.       FScreenJob := sjFlashEdit;
  3878.       TheCaption := TCaption(pClickedObject);
  3879. {create the in-place editor:}
  3880.       CreateFlashEditor;
  3881. {... and initialize it:}
  3882.       if (ClickedObjectType = soNote) then
  3883.         FFlashEdit.Text := TheCaption.Caption
  3884.        else
  3885.         FFlashEdit.Text := TTitle(pClickedObject).FullCaption;
  3886.       FFlashEdit.Height := TheCaption.Height + 10;
  3887.       FFlashEdit.Width  := 2 * TheCaption.Width;
  3888.       if (FFlashEdit.Height > FFlashEdit.Width) then
  3889.       begin
  3890. {height > width, so it is a vertical caption:}
  3891.         i := FFlashEdit.Height;
  3892.         FFlashEdit.Height := FFlashEdit.Width;
  3893.         FFlashEdit.Width := i;
  3894.       end;
  3895.       FFlashEdit.Top := TheCaption.Top;
  3896. {Have to check that the edit box is on-screen:}
  3897.       TheRight := TheCaption.Left + FFlashEdit.Width;
  3898.       if (TheRight > Width) then
  3899.         FFlashEdit.Left := TheCaption.Right - FFlashEdit.Width
  3900.       else
  3901.         FFlashEdit.Left := TheCaption.Left;
  3902.  
  3903.       FFlashEdit.Tag := Ord(ClickedObjectType);
  3904.       FFlashEdit.Font.Assign(TheCaption.Font);
  3905.  
  3906.       FFlashEdit.Visible := TRUE;
  3907.       FFlashEdit.SetFocus;
  3908.     end {Title or axis caption}
  3909.     else if (ClickedObjectType = soLegend) then
  3910.     begin
  3911.       FScreenJob := sjFlashEdit;
  3912. {create the in-place editor:}
  3913.       CreateFlashEditor;
  3914.       TheSeries := FLegend.GetHit(Selection.Left, Selection.Top, TheRect);
  3915.       FFlashEdit.Height := FLegend.FontHeight + 2;
  3916.       FFlashEdit.Width  := FLegend.ItemWidth;
  3917.       FFlashEdit.Left := TheRect.Left;
  3918.       FFlashEdit.Top := TheRect.Top - 1;
  3919.       FFlashEdit.Tag := Ord(soLegend);
  3920. {we use HelpContext because MouseDown is called after DblClick, which nukes TheSeries:}
  3921.       FFlashEdit.HelpContext := TheSeries;
  3922.       FFlashEdit.Font.Assign(FLegend.Font);
  3923.       FFlashEdit.Text := TSeries(FSeriesList[TheSeries]).Name;
  3924.       FFlashEdit.Visible := TRUE;
  3925.       FFlashEdit.SetFocus;
  3926.     end; {Legend}
  3927.   end; {editable}
  3928.  
  3929.   inherited DblClick;
  3930. end;
  3931.  
  3932. {------------------------------------------------------------------------------
  3933.     Procedure: TCustomPlot.CreateFlashEditor
  3934.   Description: Creates the FlashEdit in-place editor
  3935.        Author: Mat Ballard
  3936.  Date created: 12/1/1999
  3937. Date modified: 02/25/2000 by Mat Ballard
  3938.       Purpose: caption management
  3939.  Known Issues:
  3940.  ------------------------------------------------------------------------------}
  3941. procedure TCustomPlot.CreateFlashEditor;
  3942. {create the in-place editor:}
  3943. begin
  3944.   if (FFlashEdit = nil) then
  3945.   begin
  3946.     FFlashEdit := TEdit.Create(nil);
  3947.     FFlashEdit.Parent := Self;
  3948.     FFlashEdit.OnKeyDown := FlashEditKeyDown;
  3949.     FFlashEdit.OnExit := FlashEditExit;
  3950.     FFlashEdit.Hint := sFlashEditHint;
  3951.     FFlashEdit.ShowHint := TRUE;
  3952.   end;
  3953. end;
  3954.  
  3955. {------------------------------------------------------------------------------
  3956.     Procedure: TCustomPlot.FlashEditKeyDown
  3957.   Description: KeyDown event handler of FFlashEdit in-place editor
  3958.        Author: Mat Ballard
  3959.  Date created: 12/1/1999
  3960. Date modified: 02/25/2000 by Mat Ballard
  3961.       Purpose: Cancel the FFlashEditor if Esc pressed, or save the changed Title.
  3962.  Known Issues:
  3963.  ------------------------------------------------------------------------------}
  3964. procedure TCustomPlot.FlashEditKeyDown(
  3965.   Sender: TObject;
  3966.   var Key: Word;
  3967.   Shift: TShiftState);
  3968. begin
  3969.   if (Key = VK_ESCAPE) then  //4096
  3970.   begin
  3971.     FFlashEdit.Visible := FALSE;
  3972.     Key := 0;
  3973.   end;
  3974.  
  3975.   if (Key = VK_RETURN) then //4100
  3976.   begin
  3977. {this will throw an exception if Tag is not a valid TObjectType:}
  3978.     case TObjectType(FFlashEdit.Tag) of
  3979.       soTitle: FTitle.Caption := FFlashEdit.Text;
  3980.       {soXAxis, soYAxis}
  3981.       soXAxisTitle: FXAxis.Title.Caption := FFlashEdit.Text;
  3982.       soYAxisTitle: TTitle(pClickedObject).Caption := FFlashEdit.Text;
  3983.       {soXAxisLabel, soYAxisLabel, soYAxis2Label,
  3984.       soLeftBorder, soTopBorder, soRightBorder, soBottomBorder}
  3985. {we use HelpContext because MouseDown is called after DblClick, which nukes TheSeries:}
  3986.       soLegend: TSeries(FSeriesList[FFlashEdit.HelpContext]).Name := FFlashEdit.Text;
  3987.       soNote: TNote(pClickedObject).Caption := FFlashEdit.Text;
  3988.     end;
  3989.     FFlashEdit.Visible := FALSE;
  3990.     Key := 0;
  3991.     DoStyleChange(Self);
  3992.   end;
  3993. end;
  3994.  
  3995. {------------------------------------------------------------------------------
  3996.     Procedure: TCustomPlot.FlashEditExit
  3997.   Description: Exit event handler of FFlashEdit in-place editor
  3998.        Author: Mat Ballard
  3999.  Date created: 12/1/1999
  4000. Date modified: 02/25/2000 by Mat Ballard
  4001.       Purpose: hide the FFlashEditor
  4002.  Known Issues:
  4003.  ------------------------------------------------------------------------------}
  4004. procedure TCustomPlot.FlashEditExit(
  4005.   Sender: TObject);
  4006. begin
  4007.   FFlashEdit.Visible := FALSE;
  4008.   FFlashEdit.Text := '';
  4009.   ZeroScreenStuff;
  4010. end;
  4011.  
  4012. {------------------------------------------------------------------------------
  4013.     Procedure: TCustomPlot.KeyDown
  4014.   Description: KeyDown event handler
  4015.        Author: Mat Ballard
  4016.  Date created: 04/22/2001
  4017. Date modified: 04/22/2001 by Mat Ballard
  4018.       Purpose: This processes certain key strokes.
  4019.  Known Issues: Does not work: a CustomPanel does not seem to be able to gain focus.
  4020.  ------------------------------------------------------------------------------}
  4021. {procedure TCustomPlot.KeyDown(var Key: Word; Shift: TShiftState);
  4022. var
  4023.   OldVar, Gap: Single;
  4024. begin
  4025.   case Key of
  4026.     VK_LEFT:
  4027.       begin
  4028.         if (ssCtrl in Shift) then
  4029.         begin
  4030.           if (FXAxis.Min > FSeriesList.Xmin) then
  4031.           begin
  4032.             OldVar := FXAxis.Min;
  4033.             Gap := FXAxis.Max - FXAxis.Min;
  4034.             FXAxis.Min := FXAxis.Min - Gap;
  4035.             FXAxis.Max := FXAxis.Max - Gap;
  4036.           end;
  4037.         end;
  4038.       end;
  4039.     VK_RIGHT:
  4040.       begin
  4041.         if (ssCtrl in Shift) then
  4042.         begin
  4043.           if (FXAxis.Max < FSeriesList.Xmax) then
  4044.           begin
  4045.             OldVar := FXAxis.Max;
  4046.             Gap := FXAxis.Max - FXAxis.Min;
  4047.             FXAxis.Max := FXAxis.Max + Gap;
  4048.             FXAxis.Min := FXAxis.Min + Gap;
  4049.           end;
  4050.         end;
  4051.       end;
  4052.   end;
  4053.  
  4054.   inherited KeyDown(Key, Shift);
  4055. end;}
  4056.  
  4057. {------------------------------------------------------------------------------
  4058.     Procedure: TCustomPlot.MouseDown
  4059.   Description: MouseDown event handler
  4060.        Author: Mat Ballard
  4061.  Date created: 12/1/1999
  4062. Date modified: 08/31/2000 by Mat Ballard
  4063.       Purpose: The start of all mouse routines
  4064.  Known Issues: MouseDown gets called AFTER DblClick !
  4065.       Changes: GetTheClickedObject now moved to within the 'if (FScreenJob = sjNone) then'
  4066.  ------------------------------------------------------------------------------}
  4067. procedure TCustomPlot.MouseDown(
  4068.   Button: TMouseButton;
  4069.   Shift: TShiftState;
  4070.   X,
  4071.   Y: Integer);
  4072. begin
  4073. {Nuke any Caption:}
  4074.   FInstructions.Clear;
  4075.  
  4076. {record the beginning:}
  4077.   MouseStart.x := X;
  4078.   MouseStart.y := Y;
  4079. {set the moving object co-ordinates:}
  4080.   Selection.Left := X;
  4081.   Selection.Top := Y;
  4082.   Selection.Height := 1;
  4083.   Selection.Width := 1;
  4084.  
  4085. {  if (FScreenJob <> sjFlashEdit) then
  4086.     FFlashEdit.Visible := FALSE;}
  4087.  
  4088. {if no ScreenJob has been set yet, it could be several things:}
  4089.   if (FScreenJob = sjNone) then
  4090.   begin
  4091. {no job yet}
  4092. {what got clicked ?}
  4093.     GetTheClickedObject(X, Y);
  4094.     if (Button = mbLeft) then
  4095.     begin
  4096. {left click:}
  4097.       if (ssShift in Shift) then
  4098.       begin
  4099. {We want to zoom in:}
  4100.         FScreenJob := sjZoomIn;
  4101.       end
  4102.       else if ((ClickedObjectType <> soNone) and
  4103.                (FMovable)) then
  4104.       begin
  4105. {left clicks can lead to click and drag:}
  4106.         MouseTimer.Enabled := TRUE;
  4107.       end;
  4108.     end; {left button}
  4109.     {NOTE: if it is the right button, then the popup menu will be displayed
  4110.      at the end of the MouseUp}
  4111.   end; {if sjNone}
  4112.  
  4113.   case FScreenJob of
  4114.     {sjNone: already done}
  4115.     {sjDrag: set by MouseTimeOut
  4116.     sjRightDrag: set in MouseMove}
  4117.     sjHide: HideClick(Self);
  4118.     sjZoomIn:
  4119.       begin
  4120.         Screen.Cursor := crSize;
  4121.         OutlineTheClickedObject;
  4122.       end;
  4123.     {sjEditAxis:}
  4124.     {sjTouchNote:}
  4125.     sjMoveNotePointer: ZeroScreenStuff;
  4126.     {sjEditFont:
  4127.     sjEditPoint:
  4128.     sjEditSeries:
  4129.     sjCopySeries: ;
  4130.     sjDisplace:   ;
  4131.     sjCloneSeries: ;
  4132.     sjDeleteSeries: all done by popupmenu or option}
  4133.     sjPosition: PositionClick(Self);
  4134.     sjNearestPoint: NearestPointClick(Self);
  4135.     sjLinearize,
  4136.     sjZero,
  4137.     sjAverage,
  4138.     sjContractSeries,
  4139.     sjContractAllSeries,
  4140.     {sjSplineSeries: ;
  4141.     sjHighs,
  4142.     sjLows,
  4143.     sjMovingAverage,
  4144.     sjSmoothSeries:   ;
  4145.     sjSortSeries: ;
  4146.     sjDifferentiate:   ;
  4147.     sjIntegrate: all done by popupmenu or option}
  4148.     sjIntegral,
  4149.     sjLineOfBestFit,
  4150.     sjDualLineBestFit1,
  4151.     sjDualLineBestFit2,
  4152.     sjSelection,
  4153.     sjDualSelection1,
  4154.     sjDualSelection2:
  4155.       begin
  4156.         Screen.Cursor := crSize;
  4157.         OutlineTheSelection;
  4158.       end;
  4159.   end;
  4160.  
  4161.   inherited MouseDown(Button, Shift, X, Y);
  4162. end;
  4163.  
  4164. {------------------------------------------------------------------------------
  4165.     Procedure: TCustomPlot.MouseMove
  4166.   Description: MouseMove event handler
  4167.        Author: Mat Ballard
  4168.  Date created: 12/1/1999
  4169. Date modified: 02/25/2000 by Mat Ballard
  4170.       Purpose: Moves the dashed outline around the screen; how it moves depends on the object
  4171.  Known Issues:
  4172.  ------------------------------------------------------------------------------}
  4173. procedure TCustomPlot.MouseMove(
  4174.   Shift: TShiftState;
  4175.   X,
  4176.   Y: Integer);
  4177. var
  4178.   Gap,
  4179.   NewLeft,
  4180.   NewTop: Integer;
  4181.   Ptr: Pointer;
  4182. begin
  4183.   MouseTimer.Enabled := FALSE;
  4184.  
  4185.   if (FScreenJob = sjMoveNotePointer) then
  4186.     TNote(pClickedObject).TracePointerTo(Canvas, X, Y);
  4187.  
  4188.   if (ssLeft in Shift) then
  4189.   begin
  4190.     case FScreenJob of
  4191.       {sjNone:}
  4192.       sjDrag:
  4193.         case ClickedObjectType of
  4194.           soTitle:
  4195.             begin
  4196.               if (X < (FBorder.Left + FBorder.MidX) div 2) then
  4197.                 NewLeft := FBorder.Left
  4198.               else if (X > (FBorder.Right + FBorder.MidX) div 2) then
  4199.                 NewLeft := FBorder.Right - Selection.Width
  4200.               else
  4201.                 NewLeft := FBorder.MidX - Selection.Width div 2;
  4202.               if (Y > FXAxis.MidY) then
  4203.                 NewTop := Height - BevelGap - FTitle.Height
  4204.               else
  4205.                 NewTop := BevelGap;
  4206.               MoveTheClickedObjectTo(NewLeft, NewTop);
  4207.             end;
  4208.           soXAxis, soTopBorder, soBottomBorder:
  4209.             begin
  4210.               MoveTheClickedObjectTo(
  4211.                 TRectangle(pClickedObject).Left,
  4212.                 Y - ClickedObjectOffset.y);
  4213.             end;
  4214.           soYAxis, soLeftBorder, soRightBorder:
  4215.             begin
  4216.               MoveTheClickedObjectTo(
  4217.                 X - ClickedObjectOffset.x,
  4218.                 TRectangle(pClickedObject).Top);
  4219.             end;
  4220.           soXAxisTitle:
  4221.             begin
  4222.               if (X < (FBorder.Left + FBorder.MidX) div 2) then
  4223.                 NewLeft := FBorder.Left
  4224.               else if (X > (FBorder.Right + FBorder.MidX) div 2) then
  4225.                 NewLeft := FBorder.Right - Selection.Width
  4226.               else
  4227.                 NewLeft := FBorder.MidX - Selection.Width div 2;
  4228.               Gap := Abs(FXAxis.Title.MidY - FXAxis.MidY);
  4229.               if (Y > FXAxis.MidY) then
  4230.                 NewTop := FXAxis.MidY + Gap - FXAxis.Title.Height div 2
  4231.               else
  4232.                 NewTop := FXAxis.MidY - Gap - FXAxis.Title.Height div 2;
  4233.               MoveTheClickedObjectTo(NewLeft, NewTop);
  4234.             end;
  4235.           soYAxisTitle:
  4236.             begin
  4237. {Which Y Axis owns this Title ?}
  4238.               Ptr := TRectangle(pClickedObject).Owner;
  4239.               Gap := Abs(TRectangle(pClickedObject).MidX - TAxis(Ptr).MidX);
  4240.               if (X < TAxis(Ptr).MidX) then
  4241.                 NewLeft := TAxis(Ptr).MidX - Gap - TRectangle(pClickedObject).Width div 2
  4242.               else
  4243.                 NewLeft := TAxis(Ptr).MidX + Gap - TRectangle(pClickedObject).Width div 2;
  4244.               if (Y < (FBorder.Top + FBorder.MidY) div 2) then
  4245.                 NewTop := FBorder.Top
  4246.               else if (Y > (FBorder.Bottom + FBorder.MidY) div 2) then
  4247.                 NewTop := FBorder.Bottom - Selection.Height
  4248.               else
  4249.                 NewTop := FBorder.MidY - Selection.Height div 2;
  4250.               MoveTheClickedObjectTo(NewLeft, NewTop);
  4251.             end;
  4252.           soXAxisLabel:
  4253.             begin
  4254.               Gap := Abs(FXAxis.Labels.MidY - FXAxis.MidY);
  4255.               if (Y < FXAxis.MidY) then
  4256.                 MoveTheClickedObjectTo(Selection.Left, FXAxis.MidY - Gap -
  4257.                   FXAxis.Labels.Height div 2)
  4258.               else
  4259.                 MoveTheClickedObjectTo(Selection.Left, FXAxis.MidY + Gap -
  4260.                   FXAxis.Labels.Height div 2);
  4261.             end;
  4262.           soYAxisLabel:
  4263.             begin
  4264. {Which Y Axis owns this Title ?}
  4265.               Ptr := TRectangle(pClickedObject).Owner;
  4266.               Gap := Abs(TRectangle(pClickedObject).MidX - TAxis(Ptr).MidX);
  4267.               if (X < TAxis(Ptr).MidX) then
  4268.                 MoveTheClickedObjectTo(
  4269.                   TAxis(Ptr).MidX - Gap - TRectangle(pClickedObject).Width div 2,
  4270.                   Selection.Top)
  4271.               else
  4272.                 MoveTheClickedObjectTo(
  4273.                   TAxis(Ptr).MidX + Gap - TRectangle(pClickedObject).Width div 2,
  4274.                   Selection.Top);
  4275.             end;
  4276.           soLegend, soResult, soNote:
  4277.             begin {both of these can move freely:}
  4278.               MoveTheClickedObjectTo(
  4279.                 X - ClickedObjectOffset.x,
  4280.                 Y - ClickedObjectOffset.y);
  4281.             end;
  4282.           soSeries:
  4283.             begin
  4284.               pSeries.MoveBy(Canvas, FPlotType, X-Selection.Left, Y-Selection.Top, FOutlineWidth);
  4285.               Selection.Left := X;
  4286.               Selection.Top := Y;
  4287.             end;
  4288.         end; {end case sjDrag}
  4289.       {sjHide:}
  4290.       sjZoomIn:
  4291.         StretchTheClickedObjectTo(X, Y);
  4292.       {sjEditAxis: ;}
  4293.       {sjEditFont: ;
  4294.       sjEditPoint: ;
  4295.       sjEditSeries: ;
  4296.       sjCopySeries: ;
  4297.       sjDisplace:   ;
  4298.       sjCloneSeries: ;
  4299.       sjDeleteSeries: all done by popupmenu or option}
  4300.       {sjPosition: already done, or by popupmenu}
  4301.       {sjNearestPoint: already done, or by popupmenu}
  4302.       sjLinearize,
  4303.       sjZero,
  4304.       sjAverage,
  4305.       sjContractSeries,
  4306.       sjContractAllSeries,
  4307.       {sjSplineAxis: ;
  4308.       sjHighs,
  4309.       sjLows,
  4310.       sjMovingAverage,
  4311.       sjSmoothSeries:   ;
  4312.       sjSortSeries: ;
  4313.       sjDifferentiate:   ;
  4314.       sjIntegrate: all done by popupmenu or option}
  4315.       sjIntegral,
  4316.       sjLineOfBestFit,
  4317.       sjDualLineBestFit1,
  4318.       sjDualLineBestFit2,
  4319.       sjSelection,
  4320.       sjDualSelection1,
  4321.       sjDualSelection2:
  4322.         StretchTheClickedObjectTo(X, Y);
  4323.     end;
  4324.   end {if (ssLeft in Shift)}
  4325.   else if (ssRight in Shift) then
  4326.   begin {aha ! a right click and drag operation !}
  4327.     FScreenJob := sjRightDrag;
  4328.     StretchTheClickedObjectTo(X, Y);
  4329.   end;
  4330.  
  4331.   inherited MouseMove(Shift, X, Y);
  4332. end;
  4333.  
  4334. {------------------------------------------------------------------------------
  4335.     Procedure: TCustomPlot.MouseUp
  4336.   Description: MouseUp event handler
  4337.        Author: Mat Ballard
  4338.  Date created: 12/1/1999
  4339. Date modified: 05/30/2001 by Mat Ballard
  4340.       Purpose: Reacts to the user finishing an action with the mouse
  4341.  Known Issues:
  4342.  ------------------------------------------------------------------------------}
  4343. procedure TCustomPlot.MouseUp(
  4344.   Button: TMouseButton;
  4345.   Shift: TShiftState;
  4346.   X,
  4347.   Y: Integer);
  4348. var
  4349.   Point: TPoint;
  4350. begin
  4351.   MouseTimer.Enabled := FALSE;
  4352.  
  4353.   if (Button = mbLeft) then
  4354.   begin
  4355.     case FScreenJob of
  4356.       {sjNone:}
  4357.       sjDrag:
  4358.         begin
  4359.           OutlineTheClickedObject;
  4360.           if (SecondClickedObjectType = soNone) then
  4361.           begin
  4362.             MoveTheClickedObjectClick(Self);
  4363.           end
  4364.           else
  4365.           begin
  4366.             Point.x := X;
  4367.             Point.y := Y;
  4368.             Point := ClientToScreen(Point);
  4369.             if (pClickedObject <> nil) then
  4370.               WhichPopUpItems[0].Caption := sMoveThe +
  4371.                 TRectangle(pClickedObject).Name;
  4372.             if (pSecondClickedObject <> nil) then
  4373.               WhichPopUpItems[1].Caption := sMoveThe +
  4374.                 TRectangle(pSecondClickedObject).Name;
  4375.             WhichPopUpMenu.Popup(Point.x, Point.y);
  4376.           end;
  4377.         end;
  4378.       {sjHide:}
  4379.       sjZoomIn:
  4380.         begin
  4381.           OutlineTheClickedObject;
  4382.           SwapEnds;
  4383.           ZoomInClick(Self);
  4384.         end;
  4385.       {sjEditAxis: ;}
  4386.       sjMoveNotePointer: ZeroScreenStuff;
  4387.       {sjEditFont: ;
  4388.       sjEditPoint: ;
  4389.       sjEditSeries: ;
  4390.       sjCopySeries: ;
  4391.       sjDisplace:   ;
  4392.       sjCloneSeries: ;
  4393.       sjDeleteSeries: ;}
  4394.       {sjPosition: already done, or by popupmenu}
  4395.       {sjNearestPoint: already done, or by popupmenu}
  4396.       sjAverage:
  4397.         begin
  4398.           OutlineTheSelection;
  4399.           SwapEnds;
  4400.           AverageClick(Self);
  4401.         end;
  4402.       sjLinearize:
  4403.         begin
  4404.           OutlineTheSelection;
  4405.           SwapEnds;
  4406.           LinearizeClick(Self);
  4407.         end;
  4408.       sjZero:
  4409.         begin
  4410.           OutlineTheSelection;
  4411.           SwapEnds;
  4412.           ZeroClick(Self);
  4413.         end;
  4414.       sjContractSeries:
  4415.         begin
  4416.           OutlineTheSelection;
  4417.           SwapEnds;
  4418.           ContractSeriesClick(Self);
  4419.         end;
  4420.       sjContractAllSeries:
  4421.         begin
  4422.           OutlineTheSelection;
  4423.           SwapEnds;
  4424.           ContractAllSeriesClick(Self);
  4425.         end;
  4426.       {sjSplineSeries: ;
  4427.       sjHighs,
  4428.       sjLows,
  4429.       sjMovingAverage,
  4430.       sjSmoothSeries:   ;
  4431.       sjSortSeries: ;
  4432.       sjDifferentiate:   ;
  4433.       sjIntegrate:        ;}
  4434.       sjIntegral:
  4435.         begin
  4436.           OutlineTheSelection;
  4437.           SwapEnds;
  4438.           IntegralClick(Self);
  4439.         end;
  4440.       sjLineOfBestFit:
  4441.         begin
  4442.           OutlineTheSelection;
  4443.           SwapEnds;
  4444.           LineBestFitClick(Self);
  4445.         end;
  4446.       sjDualLineBestFit1:
  4447.         begin
  4448.           OutlineTheSelection;
  4449.           SwapEnds;
  4450.           TwoRegionLineBestFitClick(Self);
  4451.         end;
  4452.       sjDualLineBestFit2:
  4453.         begin
  4454.           OutlineTheSelection;
  4455.           SwapEnds;
  4456.           LineBestFitClick(Self);
  4457.         end;
  4458.       sjSelection:
  4459.         begin
  4460.           OutlineTheSelection;
  4461.           SwapEnds;
  4462.           Sel1.Left := Selection.Left;
  4463.           Sel1.Top := Selection.Top;
  4464.           Sel1.Right := Selection.Right;
  4465.           Sel1.Bottom := Selection.Bottom;
  4466.           DoSelection(Sel1);
  4467.         end;
  4468.       sjDualSelection1:
  4469.         begin
  4470.           OutlineTheSelection;
  4471.           SwapEnds;
  4472.           Sel1.Left := Selection.Left;
  4473.           Sel1.Top := Selection.Top;
  4474.           Sel1.Right := Selection.Right;
  4475.           Sel1.Bottom := Selection.Bottom;
  4476.           ScreenJob := sjDualLineBestFit2;
  4477.           FInstructions.Clear;
  4478.           FInstructions.Add(sDualInstruction);
  4479.           DoStyleChange(Self);
  4480.         end;
  4481.       sjDualSelection2:
  4482.         begin
  4483.           OutlineTheSelection;
  4484.           SwapEnds;
  4485.           Sel2.Left := Selection.Left;
  4486.           Sel2.Top := Selection.Top;
  4487.           Sel2.Right := Selection.Right;
  4488.           Sel2.Bottom := Selection.Bottom;
  4489.           DoDualSelection(Sel1, Sel2);
  4490.         end;
  4491.     end; {end case}
  4492.     DoStyleChange(Self);
  4493.   end {end Left Button}
  4494.   else
  4495.   begin {Right Button}
  4496.     OutlineTheClickedObject;
  4497. {$IFNDEF DELPHI1}
  4498. {what does that do to menu visibility ?}
  4499.     DetermineMenuVisibility;
  4500. {$ENDIF}
  4501. {we no longer let the ancestor run the popup:
  4502.  see note above on 'property PopupMenu':}
  4503.     Point.x := X;
  4504.     Point.y := Y;
  4505.     Point := ClientToScreen(Point);
  4506.     if (FScreenJob = sjRightDrag) then
  4507.       FDragPopUpMenu.Popup(Point.x, Point.y)
  4508.      else
  4509.       FPlotPopUpMenu.Popup(Point.x, Point.y);
  4510.   end; {end Right Button}
  4511.  
  4512. {inherited runs the popup if neccessary:}
  4513.   inherited MouseUp(Button, Shift, X, Y);
  4514. end;
  4515.  
  4516. {------------------------------------------------------------------------------
  4517.     Procedure: TCustomPlot.DoSelection
  4518.   Description: Fires the Selection event
  4519.        Author: Mat Ballard
  4520.  Date created: 09/07/2000
  4521. Date modified: 09/07/2000 by Mat Ballard
  4522.       Purpose:
  4523.  Known Issues:
  4524.  ------------------------------------------------------------------------------}
  4525. procedure TCustomPlot.DoSelection(Sel1: TRect);
  4526. begin
  4527.   if Assigned(FOnSelection) then
  4528.     OnSelection(Self, Sel1);
  4529. end;
  4530.  
  4531. {------------------------------------------------------------------------------
  4532.     Procedure: TCustomPlot.DoDualSelection
  4533.   Description: Fires the DualSelection event
  4534.        Author: Mat Ballard
  4535.  Date created: 09/07/2000
  4536. Date modified: 09/07/2000 by Mat Ballard
  4537.       Purpose:
  4538.  Known Issues:
  4539.  ------------------------------------------------------------------------------}
  4540. procedure TCustomPlot.DoDualSelection(Sel1, Sel2: TRect);
  4541. begin
  4542.   if Assigned(FOnDualSelection) then
  4543.     OnDualSelection(Self, Sel1, Sel2);
  4544. end;
  4545.  
  4546. {$IFNDEF DELPHI1}
  4547. {------------------------------------------------------------------------------
  4548.     Procedure: TCustomPlot.DetermineMenuVisibility
  4549.   Description: Sets the visibility of Axis-related menus
  4550.        Author: Mat Ballard
  4551.  Date created: 04/17/2000
  4552. Date modified: 04/17/2000 by Mat Ballard
  4553.       Purpose: menu management
  4554.  Known Issues:
  4555.  ------------------------------------------------------------------------------}
  4556. procedure TCustomPlot.DetermineMenuVisibility;
  4557. var
  4558.   i: Integer;
  4559.   SeriesVisibility: Boolean;
  4560. begin
  4561. {$IFDEF SHOWALLMENUS}
  4562.   exit;
  4563. {$ENDIF}
  4564.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].Enabled := CanPaste;
  4565.  
  4566.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  4567.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].Visible := FALSE;
  4568.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := FALSE;
  4569.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Visible := FALSE;
  4570.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Visible := FALSE;
  4571.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Visible := FALSE;
  4572.   SeriesVisibility := FALSE;
  4573.  
  4574.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuClearOverlays)].Visible :=
  4575.     (FirstOverlay >= 0);
  4576.  
  4577.   case ClickedObjectType of
  4578.     soTitle,
  4579.     soXAxisTitle, soYAxisTitle,
  4580.     soXAxisLabel, soYAxisLabel,
  4581.     soResult:
  4582.       begin
  4583.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  4584.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := TRUE;
  4585.       end;
  4586.     soNote:
  4587.       begin
  4588.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  4589.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := TRUE;
  4590.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Visible :=
  4591.           (NoteCount > 0);
  4592.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Visible :=
  4593.           (NoteCount > 0);
  4594.       end;
  4595.     soLegend:
  4596.       begin
  4597.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  4598.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := TRUE;
  4599.         if (FSeriesList.Count > 1) then
  4600.         begin
  4601.           FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Visible := TRUE;
  4602.         end;
  4603.       end;
  4604.     soXAxis, soYAxis:
  4605.       begin
  4606.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  4607.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].Visible := TRUE;
  4608.       end;
  4609.     soSeries:
  4610.       begin
  4611.         //pSeries.OutlineSeries(FOutlineWidth, Canvas);
  4612.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  4613.         SeriesVisibility := TRUE;
  4614.       end;
  4615.   else
  4616.     {soLeftBorder, soTopBorder, soRightBorder, soBottomBorder:}
  4617.     begin
  4618.       FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := FALSE;
  4619.     end;
  4620.   end;
  4621.   SetSeriesVisibility(SeriesVisibility);
  4622.  
  4623.   for i := 0 to Ord(High(TMainMenus)) do
  4624.     FPlotPopUpMenu.Items[i].Visible :=
  4625.       FPlotPopUpMenu.Items[i].Visible and
  4626.         (TMainMenus(i) in FPopupOptions.Menu);
  4627.   for i := 0 to Ord(High(TFileMenus)) do
  4628.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[i].Visible :=
  4629.       FPlotPopUpMenu.Items[Ord(mnuFile)].Items[i].Visible and
  4630.         (TFileMenus(i) in FPopupOptions.File_);
  4631.   for i := 0 to Ord(High(TEditMenus)) do
  4632.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[i].Visible :=
  4633.       FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[i].Visible and
  4634.         (TEditMenus(i) in FPopupOptions.Edit);
  4635.   for i := 0 to Ord(High(TViewMenus)) do
  4636.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[i].Visible :=
  4637.       FPlotPopUpMenu.Items[Ord(mnuView)].Items[i].Visible and
  4638.         (TViewMenus(i) in FPopupOptions.View);
  4639.   for i := 0 to Ord(High(TCalcMenus)) do
  4640.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[i].Visible :=
  4641.       FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[i].Visible and
  4642.         (TCalcMenus(i) in FPopupOptions.Calc);
  4643.  
  4644.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].Visible :=
  4645.       FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Visible;
  4646. {NewSeries means that this divider is now always visible:
  4647.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].Visible :=
  4648.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Visible;}
  4649.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].Visible :=
  4650.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Visible;
  4651.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].Visible :=
  4652.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Visible;
  4653. end;
  4654.  
  4655. {------------------------------------------------------------------------------
  4656.     Procedure: TCustomPlot.SetSeriesVisibility
  4657.   Description: Sets the visibility of Axis-related menus
  4658.        Author: Mat Ballard
  4659.  Date created: 04/17/2000
  4660. Date modified: 04/17/2000 by Mat Ballard
  4661.       Purpose: menu management
  4662.  Known Issues:
  4663.  ------------------------------------------------------------------------------}
  4664. procedure TCustomPlot.SetSeriesVisibility(Value: Boolean);
  4665. begin
  4666. {Can't do anything to Series if there is no data:}
  4667.   Value := Value and (FSeriesList.TotalNoPts > 0);
  4668.  
  4669. {The following are independent of whether or not a Series has been selected:}
  4670.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSave)].Visible :=
  4671.     (FSeriesList.TotalNoPts > 0) and FSeriesList.DataChanged;
  4672.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveAs)].Visible :=
  4673.     (FSeriesList.TotalNoPts > 0);
  4674.  
  4675.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].Visible :=
  4676.     (FAxisList.Count > 2);
  4677.  
  4678.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].Visible :=
  4679.  
  4680.     (FSeriesList.TotalNoPts > 0);
  4681.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].Visible :=
  4682.     (FSeriesList.TotalNoPts > 20);
  4683.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].Visible :=
  4684.     (FSeriesList.TotalNoPts > 20);
  4685. {$IFDEF FUNCTIONS}
  4686.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].Visible := (FSeriesList.Count > 0);
  4687.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].Visible := (FSeriesList.Count > 0);
  4688. {$ENDIF}
  4689.  
  4690. {The following DO DEPEND on whether or not a Series has been selected:}
  4691.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].Visible := Value;
  4692.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].Visible := Value;
  4693.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Visible := Value;
  4694.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].Visible := Value;
  4695.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].Visible := Value;
  4696.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].Visible := Value;
  4697.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].Visible := Value;
  4698.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Visible := Value;
  4699.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].Visible := Value;
  4700.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].Visible := Value;
  4701.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].Visible := Value;
  4702.  
  4703.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Visible := Value;
  4704.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Visible :=
  4705.     Value and
  4706.     (FSeriesList.TotalNoPts > 20) and
  4707.     (pSeries <> nil) and
  4708.     (not ((pSeries.ExternalXSeries) or (pSeries.XDataRefCount > 0)));
  4709.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].Visible :=
  4710.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Visible;
  4711.  
  4712.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSplineSeries)].Visible := Value;
  4713.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].Visible := Value;
  4714.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].Visible := Value;
  4715.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].Visible := Value;
  4716.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].Visible := Value;
  4717.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].Visible := Value;
  4718.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].Visible := Value;
  4719.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].Visible := Value;
  4720.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].Visible := Value;
  4721.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Visible := Value;
  4722.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].Visible := Value;
  4723. end;
  4724.  
  4725. {------------------------------------------------------------------------------
  4726.     Procedure: TCustomPlot.DetermineMenuEnabledness
  4727.   Description: Sets the Enabledness of Axis-related menus
  4728.        Author: Mat Ballard
  4729.  Date created: 04/17/2000
  4730. Date modified: 04/17/2000 by Mat Ballard
  4731.       Purpose: menu management
  4732.  Known Issues: called from TPlotMenu.HandleClunk
  4733.                Because we have added a "Reopen" sub-submenu, we have to
  4734.                kludge and add "1" to the index of all mnuFile menuitems.
  4735.  ------------------------------------------------------------------------------}
  4736. procedure TCustomPlot.DetermineMenuEnabledness(TheMenu: TMenu);
  4737. begin
  4738.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].Enabled :=
  4739.     CanPaste;
  4740.  
  4741.   SetSeriesEnabledness(TheMenu);
  4742.  
  4743. {Note Reopen kludge: "1+"}
  4744.   TheMenu.Items[Ord(mnuFile)].Items[1+Ord(mnuClearOverlays)].Enabled :=
  4745.     (FirstOverlay >= 0);
  4746.  
  4747.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].Enabled :=
  4748.     (FAxisList.Count > 2);
  4749.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Enabled :=
  4750.     (NoteCount > 0);
  4751.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Enabled :=
  4752.     (NoteCount > 0);
  4753.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Enabled := TRUE;
  4754.  
  4755.   TheMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Enabled := TRUE;
  4756.   TheMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Enabled :=
  4757.     (FSeriesList.Count > 1);
  4758.   TheMenu.Items[Ord(mnuView)].Items[Ord(mnuNormalView)].Enabled :=
  4759.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormalView)].Enabled;
  4760. end;
  4761.  
  4762. {------------------------------------------------------------------------------
  4763.     Procedure: TCustomPlot.SetSeriesEnabledness
  4764.   Description: Sets the Enabledness of Axis-related menus
  4765.        Author: Mat Ballard
  4766.  Date created: 04/17/2000
  4767. Date modified: 04/17/2000 by Mat Ballard
  4768.       Purpose: menu management
  4769.  Known Issues:
  4770.  ------------------------------------------------------------------------------}
  4771. procedure TCustomPlot.SetSeriesEnabledness(TheMenu: TMenu);
  4772. begin
  4773. {Note Reopen kludge: "1+"}
  4774.   TheMenu.Items[Ord(mnuFile)].Items[1+Ord(mnuSave)].Enabled :=
  4775.     (FSeriesList.TotalNoPts > 0) and FSeriesList.DataChanged;
  4776.   TheMenu.Items[Ord(mnuFile)].Items[1+Ord(mnuSaveAs)].Enabled :=
  4777.     (FSeriesList.TotalNoPts > 0);
  4778.  
  4779.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].Enabled :=
  4780.     (FSeriesList.TotalNoPts > 0);
  4781.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].Enabled :=
  4782.     (FSeriesList.TotalNoPts > 20);
  4783.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].Enabled :=
  4784.     (FSeriesList.TotalNoPts > 20);
  4785.  
  4786.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].Enabled :=
  4787.     (FSeriesList.TotalNoPts > 0);
  4788.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].Enabled :=
  4789.     (FSeriesList.TotalNoPts > 0);
  4790.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].Enabled :=
  4791.     (FSeriesList.TotalNoPts > 0);
  4792.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Enabled :=
  4793.     (FSeriesList.TotalNoPts > 0);
  4794.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].Enabled :=
  4795.     (FSeriesList.TotalNoPts > 0);
  4796. {NewSeries means that this divider is now always visible:
  4797.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].Enabled :=
  4798.     (FSeriesList.TotalNoPts > 0);}
  4799.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].Enabled :=
  4800.     (FSeriesList.TotalNoPts > 0);
  4801.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].Enabled :=
  4802.     (FSeriesList.TotalNoPts > 0);
  4803.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].Enabled :=
  4804.     (FSeriesList.TotalNoPts > 0);
  4805.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Enabled :=
  4806.     (FSeriesList.TotalNoPts > 0);
  4807.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].Enabled :=
  4808.     (FSeriesList.TotalNoPts > 0);
  4809.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].Enabled :=
  4810.     (FSeriesList.TotalNoPts > 0);
  4811.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].Enabled :=
  4812.     (FSeriesList.TotalNoPts > 0);
  4813.  
  4814.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].Enabled :=
  4815.     (FSeriesList.TotalNoPts > 0);
  4816.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Enabled :=
  4817.     (FSeriesList.TotalNoPts > 0);
  4818.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Enabled :=
  4819.      (FSeriesList.TotalNoPts > 20);
  4820.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].Enabled :=
  4821.      (FSeriesList.TotalNoPts > 20);
  4822.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSplineSeries)].Enabled :=
  4823.     (FSeriesList.TotalNoPts > 0);
  4824.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].Enabled :=
  4825.     (FSeriesList.TotalNoPts > 0);
  4826.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].Enabled :=
  4827.     (FSeriesList.TotalNoPts > 0);
  4828.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].Enabled :=
  4829.     (FSeriesList.TotalNoPts > 0);
  4830.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].Enabled :=
  4831.     (FSeriesList.TotalNoPts > 0);
  4832.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].Enabled :=
  4833.     (FSeriesList.TotalNoPts > 0);
  4834.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].Enabled :=
  4835.     (FSeriesList.TotalNoPts > 0);
  4836.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].Enabled :=
  4837.     (FSeriesList.TotalNoPts > 0);
  4838.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].Enabled :=
  4839.     (FSeriesList.TotalNoPts > 0);
  4840.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].Enabled :=
  4841.     (FSeriesList.TotalNoPts > 0);
  4842.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Enabled :=
  4843.     (FSeriesList.TotalNoPts > 0);
  4844.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].Enabled :=
  4845.     (FSeriesList.TotalNoPts > 0);
  4846.   {$IFDEF FUNCTIONS}
  4847.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].Visible := (FSeriesList.Count > 0);
  4848.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].Visible := (FSeriesList.Count > 0);
  4849.   {$ENDIF}
  4850. end;
  4851. {$ENDIF}
  4852.  
  4853. {------------------------------------------------------------------------------
  4854.     Procedure: SwapEnds
  4855.   Description: Swaps the selection's Left-Right and Top-Bottom if needed
  4856.        Author: Mat Ballard
  4857.  Date created: 12/1/1999
  4858. Date modified: 02/25/2000 by Mat Ballard
  4859.       Purpose: manageing region selections
  4860.  Known Issues:
  4861.  ------------------------------------------------------------------------------}
  4862. procedure TCustomPlot.SwapEnds;
  4863. var
  4864.   iX: Integer;
  4865. begin
  4866. {swap Left and Right:}
  4867.   if (Selection.Left > Selection.Right) then
  4868.   begin
  4869.     iX := Selection.Left;
  4870.     Selection.Left := Selection.Right;
  4871.     Selection.Right := iX;
  4872.   end;
  4873.  
  4874. {swap Top and Bottom:}
  4875.   if (Selection.Top > Selection.Bottom) then
  4876.   begin
  4877.     iX := Selection.Top;
  4878.     Selection.Top := Selection.Bottom;
  4879.     Selection.Bottom := iX;
  4880.   end;
  4881. end;
  4882.  
  4883. {------------------------------------------------------------------------------
  4884.     Procedure: SetResult
  4885.   Description: Performs calculations on Screen Data
  4886.        Author: Mat Ballard
  4887.  Date created: 12/1/1999
  4888. Date modified: 02/25/2000 by Mat Ballard
  4889.       Purpose: Finishes off Line of Best Fit determinations
  4890.  Known Issues:
  4891.  ------------------------------------------------------------------------------}
  4892. procedure TCustomPlot.SetResult(
  4893.   Slope,
  4894.   Intercept,
  4895.   Rsq: Single);
  4896. begin
  4897.   if (pSeries.XAxis.LogScale) then
  4898.     FResult.Caption := 'Ln(' + pSeries.XAxis.Title.Caption + ')  =  '
  4899.    else
  4900.     FResult.Caption := pSeries.XAxis.Title.Caption + '  =  ';
  4901.   FResult.Caption := FResult.Caption + FloatToStrF(Intercept, ffGeneral, 5, 3) + ' + ';
  4902.   if (pSeries.XAxis.LogScale) then
  4903.     FResult.Caption := FResult.Caption + FloatToStrF(Slope, ffGeneral, 5, 3) +
  4904.       ' ╫ ' + sLn + '(' + pSeries.YAxis.Title.Caption + '),  ' + sRSquare + ' = '
  4905.    else
  4906.     FResult.Caption := FResult.Caption + FloatToStrF(Slope, ffGeneral, 5, 3) +
  4907.       ' ╫ ' + pSeries.YAxis.Title.Caption + ', ' + sRSquare + ' = ';
  4908.   FResult.Caption := FResult.Caption + FloatToStrF(Rsq, ffGeneral, 5, 3);
  4909.   ClipBoard.AsText := FResult.Caption;
  4910.   FResult.Font.Color := pSeries.Pen.Color;
  4911.   FResult.Left := Selection.Left;
  4912.   FResult.Top := Selection.Top;
  4913.   FResult.Visible := TRUE;
  4914. end;
  4915.  
  4916. {------------------------------------------------------------------------------
  4917.     Procedure: TCustomPlot.MouseTimeOut
  4918.   Description: responds to the mouse button being held down
  4919.        Author: Mat Ballard
  4920.  Date created: 12/1/1999
  4921. Date modified: 02/25/2000 by Mat Ballard
  4922.       Purpose: Frees the timer, identifies the clicked object, outlines it, and prepares to move it
  4923.  Known Issues:
  4924.  ------------------------------------------------------------------------------}
  4925. procedure TCustomPlot.MouseTimeOut(
  4926.   Sender: TObject);
  4927. {If this is fired, then the user has held the mouse still for one second
  4928.  on a screen object: this is a cue for a move.}
  4929. begin
  4930.   MouseTimer.Enabled := FALSE;
  4931.  
  4932.   if (ClickedObjectType = soNone) then exit;
  4933.  
  4934.   if (FScreenJob = sjTouchNotePointer) then
  4935.   begin
  4936. {$IFDEF COMPILER3_UP}
  4937.     Screen.Cursor := crScope;
  4938. {$ENDIF}
  4939.     FScreenJob := sjMoveNotePointer;
  4940.   end
  4941.   else
  4942.   begin
  4943.     FScreenJob := sjDrag;
  4944. {$IFDEF COMPILER3_UP}
  4945.     Screen.Cursor := crHandPoint;
  4946. {$ENDIF}
  4947.     if (ClickedObjectType = soSeries) then
  4948.     begin
  4949.       pSeries.Outline(Self.Canvas, FPlotType, FOutlineWidth);
  4950.     end
  4951.     else
  4952.     begin
  4953. {This is fascinating: the following call attempts to assign all the TAxis
  4954.  properties of pClickedObject to Selection - which of course pukes:
  4955.     Selection.Assign(TRectangle(pClickedObject));
  4956.  So we have to assign position manually:}
  4957.       if (pClickedObject <> nil) then
  4958.       begin
  4959.         Selection.Left := TRectangle(pClickedObject).Left;
  4960.         Selection.Top := TRectangle(pClickedObject).Top;
  4961.         Selection.Width := TRectangle(pClickedObject).Width;
  4962.         Selection.Height := TRectangle(pClickedObject).Height;
  4963.       end;
  4964.  
  4965.       OutlineTheClickedObject;
  4966.     end;
  4967.   end; {sjTouchNote}
  4968. end;
  4969.  
  4970. {------------------------------------------------------------------------------
  4971.     Procedure: TCustomPlot.GetTheClickedObject
  4972.   Description: identifies the object(s) that was clicked on
  4973.        Author: Mat Ballard
  4974.  Date created: 12/1/1999
  4975. Date modified: 02/25/2000 by Mat Ballard
  4976.       Purpose: sets ClickedObjectType and SecondClickedObjectType, and TheSeries if it was a Axis.
  4977.  Known Issues:
  4978.  ------------------------------------------------------------------------------}
  4979. procedure TCustomPlot.GetTheClickedObject(
  4980.   X,
  4981.   Y: Integer);
  4982. var
  4983.   i: Integer;
  4984.   MinDistance: Single;
  4985.   ANote: TNote;
  4986.   TheRect: TRect;
  4987. begin
  4988.   pClickedObject := nil;
  4989.   pSecondClickedObject := nil;
  4990.   ClickedObjectType := soNone;
  4991.  
  4992. {page control while zoomed in ?}  
  4993.   if (FPageButtons[0] <> nil) then
  4994.   begin
  4995.     if ((X > Self.Width - 3*FPageButtons[0].Width) and
  4996.         (Y > Self.Height - 2*FPageButtons[0].Height)) then
  4997.     begin
  4998. { x2x
  4999.   031  is the layout:}
  5000.       if (Y > Self.Height - FPageButtons[0].Height) then
  5001.       begin
  5002.         if (X < Self.Width - 2*FPageButtons[0].Width) then
  5003.           PageButtonClick(0)
  5004.         else if (X < Self.Width - FPageButtons[0].Width) then
  5005.           PageButtonClick(3)
  5006.         else
  5007.           PageButtonClick(1);
  5008.       end
  5009.       else
  5010.       begin
  5011.         if ((X >= Self.Width - 2*FPageButtons[0].Width) and
  5012.             (X < Self.Width - FPageButtons[0].Width)) then
  5013.           PageButtonClick(2);  
  5014.       end;
  5015.     end;
  5016.   end;
  5017.  
  5018.   for i := 1 to ScreenObjectList.Count-1 do
  5019.   begin
  5020. {identify the clicked-on object:}
  5021.     if (TRectangle(ScreenObjectList.Items[i]).ClickedOn(X, Y)) then
  5022.     begin
  5023.       if (pClickedObject = nil) then
  5024.       begin
  5025.         pClickedObject := ScreenObjectList.Items[i];
  5026.         ClickedObjectType := TObjectType(TRectangle(pClickedObject).Tag);
  5027.         ClickedObjectOffset.x := X - TRectangle(pClickedObject).Left;
  5028.         ClickedObjectOffset.y := Y - TRectangle(pClickedObject).Top;
  5029.         if ((ClickedObjectType = soXAxis) or
  5030.             (ClickedObjectType = soYAxis)) then
  5031.         begin
  5032.           pAxis := TAxis(pClickedObject);
  5033.           TheAxis := FAxisList.IndexOf(pAxis);
  5034.         end;
  5035.       end
  5036.       else
  5037.       begin
  5038. {there are two objects under the mouse: usually an axis and a border:}
  5039.         pSecondClickedObject := ScreenObjectList.Items[i];
  5040.         SecondClickedObjectType := TObjectType(TRectangle(pSecondClickedObject).Tag);
  5041.         exit;
  5042.       end;
  5043.     end; {clicked on object i}
  5044.   end; {for}
  5045.  
  5046.   if (ClickedObjectType = soLegend) then
  5047.   begin
  5048.     FLegend.GetHit(X, Y, TheRect);
  5049.   end;
  5050.  
  5051.   if (ClickedObjectType = soNone) then
  5052.   begin
  5053. {was it a note end ?}
  5054.     for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  5055.     begin
  5056.       if (TObject(ScreenObjectList.Items[i]) is TNote) then
  5057.       begin
  5058.         ANote := TNote(ScreenObjectList.Items[i]);
  5059.         if ((Abs(ANote.ArrowLeft - X) < FOutlineWidth) or
  5060.             (Abs(ANote.ArrowTop - Y) < FOutlineWidth)) then
  5061.         begin
  5062.           ClickedObjectType := soNote;
  5063.           pClickedObject := ANote;
  5064.           FScreenJob := sjTouchNotePointer;
  5065.         end;
  5066.       end;
  5067.     end;
  5068.   end;
  5069.  
  5070. {If nothing yet clicked on ...}
  5071.   if (ClickedObjectType = soNone) then
  5072.   begin
  5073.     if ((FPlotType = ptXY) or
  5074.         (FPlotType = ptError) or
  5075.         (FPlotType = ptMultiple) or
  5076.         (FPlotType = ptBubble) or
  5077.         (FPlotType = ptColumn) or
  5078.         (FPlotType = ptStack) or
  5079.         (FPlotType = ptNormStack) or
  5080.         (FPlotType = ptPie)) then
  5081.     begin
  5082. {was it a Series ?}
  5083.       ThePointNumber := FSeriesList.GetNearestPoint(
  5084.         FPlotType,
  5085.         FColumnGap,
  5086.         X, Y, //Selection.Left, Selection.Top,
  5087.         TheSeries,
  5088.         MinDistance,
  5089.         pSeries);
  5090. {give it a wide hit range:}
  5091.       if (MinDistance < (FOutlineWidth)) then
  5092.       begin
  5093.         ClickedObjectType := soSeries;
  5094.         if (FPlotType <= ptBubble) then
  5095.           pSeries.GenerateXYOutline;
  5096.       end;
  5097.     end; {FPlotType}
  5098.   end; {ClickedObjectType = soNone}
  5099. end;
  5100.  
  5101. {------------------------------------------------------------------------------
  5102.     Procedure: TCustomPlot.ProcessClickedObject
  5103.   Description: Adjusts the geometry of a moved (clicked and dragged) object
  5104.        Author: Mat Ballard
  5105.  Date created: 12/1/1999
  5106. Date modified: 02/25/2000 by Mat Ballard
  5107.       Purpose: sets appropriate property(ies) of the object that has been manipulated on screen
  5108.  Known Issues:
  5109.  ------------------------------------------------------------------------------}
  5110. procedure TCustomPlot.ProcessClickedObject(
  5111.   pObject: Pointer;
  5112.   TheObjectType: TObjectType);
  5113. var
  5114.   NewMousePoint: TPoint;
  5115. begin
  5116.   case TheObjectType of
  5117.     soTitle:
  5118.       begin
  5119.         if (Selection.Left = FBorder.Left) then
  5120.           FTitle.Alignment := taLeftJustify
  5121.          else if (Selection.Right = FBorder.Right) then
  5122.           FTitle.Alignment := taRightJustify
  5123.          else
  5124.           FTitle.Alignment := taCenter;
  5125.         if (Selection.Top < FBorder.MidY) then
  5126.           FTitle.Orientation := orLeft
  5127.          else
  5128.           FTitle.Orientation := orRight;
  5129.       end;
  5130.  
  5131.     soLegend:
  5132.       begin
  5133.         FLegend.Left := Selection.Left;
  5134.         FLegend.Top := Selection.Top;
  5135.       end;
  5136.  
  5137.     soResult:
  5138.       begin
  5139.         FResult.Left := Selection.Left;
  5140.         FResult.Top := Selection.Top;
  5141.       end;
  5142.  
  5143.     soXAxis:
  5144.       begin
  5145.         FXAxis.Intercept := FYAxis.YofF(Selection.MidY);
  5146.       end;
  5147.  
  5148.     soXAxisTitle:
  5149.       begin
  5150.         if (Selection.Left = FBorder.Left) then
  5151.           FXAxis.Title.Alignment := taLeftJustify
  5152.          else if (Selection.Right = FBorder.Right) then
  5153.           FXAxis.Title.Alignment := taRightJustify
  5154.          else
  5155.           FXAxis.Title.Alignment := taCenter;
  5156.         if (Selection.Top < FXAxis.MidY) then
  5157.           FXAxis.Title.Orientation := orLeft
  5158.          else
  5159.           FXAxis.Title.Orientation := orRight;
  5160.       end;
  5161.     soXAxisLabel:
  5162.       begin
  5163.         if (Selection.Top < FXAxis.MidY) then
  5164.           FXAxis.TickDirection := orLeft
  5165.          else
  5166.           FXAxis.TickDirection := orRight;
  5167.       end;
  5168.  
  5169.     soYAxis:
  5170.       begin
  5171.         TAxis(pObject).Intercept := FXAxis.XofF(Selection.MidX);
  5172.         Resize;
  5173.       end;
  5174.     soYAxisTitle:
  5175.       begin
  5176.         if (Selection.Left < TAxis(TTitle(pObject).Owner).MidX) then
  5177.           TTitle(pObject).Orientation := orLeft
  5178.          else
  5179.           TTitle(pObject).Orientation := orRight;
  5180.         if (Selection.Top = FBorder.Top) then
  5181.           TTitle(pObject).Alignment := taRightJustify
  5182.          else if (Selection.Bottom = FBorder.Bottom) then
  5183.           TTitle(pObject).Alignment := taLeftJustify
  5184.          else
  5185.           TTitle(pObject).Alignment := taCenter;
  5186.       end;
  5187.     soYAxisLabel:
  5188.       begin
  5189.         if (Selection.Left < TAxis(TAxisLabel(pObject).Owner).MidX) then
  5190.           TAxis(TAxisLabel(pObject).Owner).TickDirection := orLeft
  5191.          else
  5192.           TAxis(TAxisLabel(pObject).Owner).TickDirection := orRight;
  5193.       end;
  5194.  
  5195.     soLeftBorder: FBorder.Left := Selection.MidX;
  5196.     soRightBorder: FBorder.Right := Selection.MidX;
  5197.     soTopBorder: FBorder.Top := Selection.MidY;
  5198.     soBottomBorder: FBorder.Bottom := Selection.MidY;
  5199.  
  5200.     soNote:
  5201.       begin
  5202.         TNote(pObject).Left := Selection.Left;
  5203.         TNote(pObject).Top := Selection.Top;
  5204. {now lets move the note pointer:}        
  5205. {$IFDEF COMPILER3_UP}
  5206.         Screen.Cursor := crScope;
  5207. {$ENDIF}
  5208.         FScreenJob := sjMoveNotePointer;
  5209.         NewMousePoint.x := TNote(pObject).ArrowLeft;
  5210.         NewMousePoint.Y := TNote(pObject).ArrowTop;
  5211.         ClientToScreen(NewMousePoint);
  5212. {$IFDEF BCB}
  5213.         SetCursorPos(NewMousePoint.x, NewMousePoint.y);
  5214. {$ELSE} {BCB doesn't like:}
  5215.         Mouse.CursorPos := ClientToScreen(NewMousePoint);
  5216. {$ENDIF}
  5217.         exit;
  5218.       end;
  5219.  
  5220.     soSeries: { already moved by direct change of DeltaX and DeltaY properties}
  5221.       begin
  5222.  
  5223.       end;
  5224.   end; {case TheObjectType}
  5225.   ZeroScreenStuff;
  5226.   DoStyleChange(Self);
  5227. end;
  5228.  
  5229. {------------------------------------------------------------------------------
  5230.     Procedure: TCustomPlot.OutlineTheClickedObject
  5231.   Description: Outlines The Clicked Object
  5232.        Author: Mat Ballard
  5233.  Date created: 12/1/1999
  5234. Date modified: 02/25/2000 by Mat Ballard
  5235.       Purpose: gives the user a guide to what they are manipulating with the mouse
  5236.  Known Issues:
  5237.  ------------------------------------------------------------------------------}
  5238. procedure TCustomPlot.OutlineTheClickedObject;
  5239. begin
  5240.   if (ClickedObjectType = soSeries) then
  5241.     pSeries.Outline(Self.Canvas, FPlotType, FOutlineWidth)
  5242.    else
  5243.     Selection.Outline(Self.Canvas);
  5244. end;
  5245.  
  5246. {------------------------------------------------------------------------------
  5247.     Procedure: TCustomPlot.OutlineTheSelection
  5248.   Description: Outlines The Moving Object
  5249.        Author: Mat Ballard
  5250.  Date created: 12/1/1999
  5251. Date modified: 02/25/2000 by Mat Ballard
  5252.       Purpose: gives the user a guide to what they are moving with the mouse
  5253.  Known Issues:
  5254.  ------------------------------------------------------------------------------}
  5255. procedure TCustomPlot.OutlineTheSelection;
  5256. begin
  5257.   Canvas.Pen.Color := clBlack;
  5258.   Canvas.Pen.Mode := pmNotXOR;
  5259.   Canvas.Pen.Style := psDash;
  5260.   Canvas.Rectangle(Selection.Left, Selection.Top,
  5261.                    Selection.Right, Selection.Bottom);
  5262. end;
  5263.  
  5264. {------------------------------------------------------------------------------
  5265.     Procedure: TCustomPlot.MoveTheClickedObjectTo
  5266.   Description: This moves the clicked object outline TO (X, Y)
  5267.        Author: Mat Ballard
  5268.  Date created: 12/1/1999
  5269. Date modified: 02/25/2000 by Mat Ballard
  5270.       Purpose: gives the user a guide to what they are moving with the mouse
  5271.  Known Issues:
  5272.  ------------------------------------------------------------------------------}
  5273. procedure TCustomPlot.MoveTheClickedObjectTo(
  5274.   X,
  5275.   Y: Integer);
  5276. begin
  5277.   if ((Selection.Left = X) and (Selection.Top = Y)) then exit;
  5278.  
  5279. {erase the old outline:}
  5280.   OutlineTheClickedObject;
  5281.  
  5282. {re-initialize the Selection:}
  5283.   Selection.Left := X;
  5284.   Selection.Top := Y;
  5285.  
  5286. {create the new outline:}
  5287.   OutlineTheClickedObject;
  5288. end;
  5289.  
  5290. {------------------------------------------------------------------------------
  5291.     Procedure: TCustomPlot.StretchTheClickedObjectTo
  5292.   Description: Stretch The Clicked Object To
  5293.        Author: Mat Ballard
  5294.  Date created: 12/1/1999
  5295. Date modified: 02/25/2000 by Mat Ballard
  5296.       Purpose: gives the user a guide to what they are selecting with the mouse
  5297.  Known Issues:
  5298.  ------------------------------------------------------------------------------}
  5299. procedure TCustomPlot.StretchTheClickedObjectTo(
  5300.   X,
  5301.   Y: Integer);
  5302. {This moves the far (right, bottom) point of the Stretched object outline TO (X, Y).}
  5303. begin
  5304.   if ((Selection.Right = X) and (Selection.Bottom = Y)) then
  5305.     exit;
  5306.  
  5307. {erase the old outline:}
  5308.   OutlineTheSelection;
  5309.  
  5310. {re-initialize the Selection:}
  5311.   Selection.Right := X;
  5312.   Selection.Bottom := Y;
  5313.  
  5314. {create the new outline:}
  5315.   OutlineTheSelection;
  5316. end;
  5317.  
  5318. {------------------------------------------------------------------------------
  5319.     Procedure: MoveTheClickedObjectClick
  5320.   Description: deals with the end of a screen operation at MouseUp
  5321.        Author: Mat Ballard
  5322.  Date created: 12/1/1999
  5323. Date modified: 02/25/2000 by Mat Ballard
  5324.       Purpose: Processes the first Clicked Object
  5325.  Known Issues:
  5326.  ------------------------------------------------------------------------------}
  5327. procedure TCustomPlot.MoveTheClickedObjectClick(
  5328.   Sender: TObject);
  5329. begin
  5330.   ProcessClickedObject(pClickedObject, ClickedObjectType);
  5331. end;
  5332.  
  5333. {------------------------------------------------------------------------------
  5334.     Procedure: MoveSecondClickedObjectClick
  5335.   Description: deals with the end of a screen operation at MouseUp
  5336.        Author: Mat Ballard
  5337.  Date created: 12/1/1999
  5338. Date modified: 02/25/2000 by Mat Ballard
  5339.       Purpose: Processes the SECOND Clicked Object
  5340.  Known Issues:
  5341.  ------------------------------------------------------------------------------}
  5342. procedure TCustomPlot.MoveSecondClickedObjectClick(
  5343.   Sender: TObject);
  5344. begin
  5345.   ProcessClickedObject(pSecondClickedObject, SecondClickedObjectType);
  5346. end;
  5347.  
  5348. {General public methods -----------------------------------------------------}
  5349. {------------------------------------------------------------------------------
  5350.     Procedure: TCustomPlot.AddData
  5351.   Description: Add data to the graph
  5352.        Author: Mat Ballard
  5353.  Date created: 12/1/1999
  5354. Date modified: 02/25/2000 by Mat Ballard
  5355.       Purpose: adds data to all Axis simultaneously, avoiding re-drawing the data 
  5356.  Known Issues:
  5357.  ------------------------------------------------------------------------------}
  5358. procedure TCustomPlot.AddData(
  5359.   NoPoints: Integer;
  5360.   XYArray: pXYArray);
  5361. var
  5362.   i: Integer;
  5363. begin
  5364.   if ((NoPoints > 0) and (NoPoints <= FSeriesList.Count)) then
  5365.   begin
  5366.     if (FDisplayMode <> dmHistory) then
  5367.     begin
  5368.       for i := 0 to NoPoints-1 do
  5369.       begin
  5370.         TSeries(FSeriesList.Items[i]).AddDrawPoint(XYArray^[i].X, XYArray^[i].Y, Canvas);
  5371.       end;
  5372.     end
  5373.     else
  5374.     begin
  5375.       case FPlotType of
  5376.         ptXY:
  5377.           begin
  5378. {erase the old curve:}
  5379.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5380.             for i := 0 to NoPoints-1 do
  5381.             begin
  5382.               TSeries(FSeriesList.Items[i]).AddPoint(XYArray^[i].X, XYArray^[i].Y, FALSE, FALSE);
  5383.             end;
  5384. {draw the new one:}
  5385.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5386.           end;
  5387.         ptMultiple:
  5388.           begin
  5389. {erase the old curve:}
  5390.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5391.             Canvas.Pen.Assign(FMultiplePen);
  5392.             FSeriesList.DrawHistoryMultiple(Canvas, FMultiplicity);
  5393.             for i := 0 to NoPoints-1 do
  5394.             begin
  5395.               TSeries(FSeriesList.Items[i]).AddPoint(XYArray^[i].X, XYArray^[i].Y, FALSE, FALSE);
  5396.             end;
  5397. {draw the new one:}
  5398.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5399.             Canvas.Pen.Assign(FMultiplePen);
  5400.             FSeriesList.DrawHistoryMultiple(Canvas, FMultiplicity);
  5401.           end;
  5402.         ptColumn:
  5403.           begin
  5404.           end;
  5405.         {ptPipeLine:
  5406.           begin
  5407.           end;}
  5408.       end;
  5409.     end;
  5410.   end
  5411.   else
  5412.     EMathError.CreateFmt(sAddDataError, [FSeriesList.Count]);
  5413. end;
  5414.  
  5415. {------------------------------------------------------------------------------
  5416.      Function: TCustomPlot.AddSeries
  5417.   Description: wrapper for TSeriesList.Add
  5418.        Author: Mat Ballard
  5419.  Date created: 12/1/1999
  5420. Date modified: 02/25/2000 by Mat Ballard
  5421.       Purpose: Adds a new, empty data Series to the graph
  5422.  Return Value: the Index of the new Series
  5423.  Known Issues:
  5424.  ------------------------------------------------------------------------------}
  5425. function TCustomPlot.AddSeries(
  5426.   XSeriesIndex: Integer): Integer;
  5427. begin
  5428.   AddSeries := FSeriesList.Add(XSeriesIndex);
  5429. end;
  5430.  
  5431. {------------------------------------------------------------------------------
  5432.      Function: TCustomPlot.AddExternal
  5433.   Description: wrapper for TSeriesList.AddExternal
  5434.        Author: Mat Ballard
  5435.  Date created: 12/1/1999
  5436. Date modified: 02/25/2000 by Mat Ballard
  5437.       Purpose: Adds a new data Series that is maintained elsewhere to the graph
  5438.  Known Issues:
  5439.  ------------------------------------------------------------------------------}
  5440. function TCustomPlot.AddExternalSeries(
  5441.   XPointer,
  5442.   YPointer: pSingleArray;
  5443.   NumberOfPoints: Integer): Integer;
  5444. begin
  5445.   AddExternalSeries := FSeriesList.AddExternal(XPointer, YPointer, NumberOfPoints);
  5446. end;
  5447.  
  5448. {------------------------------------------------------------------------------
  5449.      Function: TCustomPlot.AddInternal
  5450.   Description: wrapper for TSeriesList.AddInternal
  5451.        Author: Mat Ballard
  5452.  Date created: 12/1/1999
  5453. Date modified: 02/25/2000 by Mat Ballard
  5454.       Purpose: Adds a new data Series from elsewhere to the graph, and saves it internally
  5455.  Known Issues:
  5456.  ------------------------------------------------------------------------------}
  5457. function TCustomPlot.AddInternalSeries(
  5458.   XPointer,
  5459.   YPointer: pSingleArray; 
  5460.   NumberOfPoints: Integer): Integer;
  5461. begin
  5462.   AddInternalSeries := FSeriesList.AddInternal(XPointer, YPointer, NumberOfPoints);
  5463. end;
  5464.  
  5465. {------------------------------------------------------------------------------
  5466.     Procedure: TCustomPlot.CloneSeries
  5467.   Description: wrapper for TSeriesList.CloneSeries
  5468.        Author: Mat Ballard
  5469.  Date created: 12/1/1999
  5470. Date modified: 02/25/2000 by Mat Ballard
  5471.       Purpose: Clones the specified Series
  5472.  Known Issues:
  5473.  ------------------------------------------------------------------------------}
  5474. function TCustomPlot.CloneSeries(
  5475.   TheSeries: Integer): Integer;
  5476. begin
  5477.   CloneSeries := FSeriesList.CloneSeries(TheSeries);
  5478. end;
  5479.  
  5480. {------------------------------------------------------------------------------
  5481.     Procedure: TCustomPlot.DeleteSeries
  5482.   Description: wrapper for TSeriesList.DeleteSeries
  5483.        Author: Mat Ballard
  5484.  Date created: 12/1/1999
  5485. Date modified: 02/25/2000 by Mat Ballard
  5486.       Purpose: Deletes the specified Series
  5487.  Known Issues:
  5488.  ------------------------------------------------------------------------------}
  5489. procedure TCustomPlot.DeleteSeries(
  5490.   Index: Integer);
  5491. begin
  5492.   FSeriesList.DeleteSeries(Index, not(csDesigning in ComponentState));
  5493. end;
  5494.  
  5495. {Responding to user (right) click menus -------------------------------------}
  5496. {------------------------------------------------------------------------------
  5497.     Procedure: TCustomPlot.CopyClick
  5498.   Description: The public copying method
  5499.        Author: Mat Ballard
  5500.  Date created: 12/1/1999
  5501. Date modified: 02/25/2000 by Mat Ballard
  5502.       Purpose: copies the graph to the clipboard, in all formats simultaneously
  5503.  Known Issues:
  5504.  ------------------------------------------------------------------------------}
  5505. procedure TCustomPlot.CopyClick(
  5506.   Sender: TObject);
  5507. begin
  5508. {$IFDEF MSWINDOWS}
  5509.   ClipBoardFormatForHTML := RegisterClipboardFormat('cfHTML');
  5510.   ClipBoard.Open;
  5511.   try
  5512. {copy all three formats to the clipboard at once:}
  5513.     CopyText;
  5514.     CopyHTML(ClipBoardFormatForHTML);
  5515.     CopyBitmap;
  5516.     CopyDrawing(TRUE);
  5517.   finally
  5518.     ClipBoard.Close;
  5519.   end;
  5520. {$ENDIF}
  5521. {$IFDEF LINUX}
  5522.   CopyText;
  5523.   CopyHTML(ClipBoardFormatForHTML);
  5524.   CopyBitmap;
  5525. {$ENDIF}
  5526. end;
  5527.  
  5528. {------------------------------------------------------------------------------
  5529.     Procedure: TCustomPlot.HideClick
  5530.   Description: Hides part of the graph
  5531.        Author: Mat Ballard
  5532.  Date created: 12/1/1999
  5533. Date modified: 02/25/2000 by Mat Ballard
  5534.       Purpose: makes the selected object invisible
  5535.  Known Issues:
  5536.  ------------------------------------------------------------------------------}
  5537. procedure TCustomPlot.HideClick(
  5538.   Sender: TObject);
  5539. begin
  5540.   if (Sender is TPlotMenu) then
  5541.   begin
  5542.     FInstructions.Clear;
  5543.     FInstructions.Add(sHideInstruction);
  5544.     ScreenJob := sjHide;
  5545.     DoStyleChange(Self);
  5546.     exit;
  5547.   end;
  5548.  
  5549.   case ClickedObjectType of
  5550.     soTitle: FTitle.Visible := FALSE;
  5551.     soLegend: FLegend.Visible := FALSE;
  5552.     soResult: FResult.Visible := FALSE;
  5553.     soNote: TNote(pClickedObject).Visible := FALSE;
  5554.     soXAxis: FXAxis.Visible := FALSE;
  5555.     soYAxis: TAxis(pClickedObject).Visible := FALSE;
  5556.     soXAxisTitle: FXAxis.Title.Visible := FALSE;
  5557.     soYAxisTitle: TTitle(pClickedObject).Visible := FALSE;
  5558.     soXAxisLabel: FXAxis.Labels.Visible := FALSE;
  5559.     soYAxisLabel: TAxisLabel(pClickedObject).Visible := FALSE;
  5560.     soSeries: pSeries.Visible := FALSE;
  5561.   end;
  5562.   DoStyleChange(Self);
  5563.   ZeroScreenStuff;
  5564. end;
  5565.  
  5566. {$IFDEF MSWINDOWS}
  5567. {------------------------------------------------------------------------------
  5568.     Procedure: TCustomPlot.PrintClick
  5569.   Description: The public printing method
  5570.        Author: Mat Ballard
  5571.  Date created: 12/1/1999
  5572. Date modified: 02/25/2000 by Mat Ballard
  5573.       Purpose: Print the graph
  5574.  Known Issues: We kludge this one a bit by creating a metafile, then playing it
  5575.                on the printer canvas. It would be nicer to draw directly on the
  5576.                printer canvas.
  5577.  ------------------------------------------------------------------------------}
  5578. procedure TCustomPlot.PrintClick(
  5579.   Sender: TObject);
  5580. var
  5581.   i: Integer;
  5582.   Copies: Integer;
  5583.   PrintDialog: TPrintDialog;
  5584.   PrintBorder: TRect;
  5585.   HorzSizeMM, VertSizeMM: Integer;
  5586. {for the metafile:}
  5587.   AMetafile: TMetafile;
  5588.   AMetafileCanvas: TMetafileCanvas;
  5589. begin
  5590.   Printer.Orientation := FPrintOrientation;
  5591.   PrintDialog := TPrintDialog.Create(Self);
  5592.   PrintDialog.Options := [poPrintToFile, poWarning];
  5593.   if (PrintDialog.Execute) then
  5594.   begin
  5595.     if (PrintDialog.Copies > 1) then
  5596.       Copies := PrintDialog.Copies
  5597.      else
  5598.       Copies := 1;
  5599.     Printer.Title := Application.ExeName + ' - ' + FTitle.Caption;
  5600.  
  5601. {$IFDEF MSWINDOWS}
  5602.     HorzSizeMM := GetDeviceCaps(Printer.Handle, HORZSIZE);
  5603.     VertSizeMM := GetDeviceCaps(Printer.Handle, VERTSIZE);
  5604. {$ENDIF}
  5605.  
  5606. {Set the margins to 25 mm:}
  5607.     PrintBorder.Left := 25 * (Printer.PageWidth div HorzSizeMM);
  5608.     PrintBorder.Top := 25 * (Printer.PageHeight div VertSizeMM);
  5609.     PrintBorder.Right := Printer.PageWidth - PrintBorder.Left;
  5610.     PrintBorder.Bottom := Printer.PageHeight - PrintBorder.Top;
  5611.  
  5612.     AMetafile := TMetafile.Create;
  5613.   {$IFNDEF DELPHI1}
  5614.     AMetafile.Enhanced := TRUE;
  5615.   {$ENDIF}
  5616.  
  5617.   {NOTE: you _MUST_ set the height and width before doing anything !}
  5618.     AMetafile.Height := Height; {PrintBorder.Bottom - PrintBorder.Top;}
  5619.     AMetafile.Width := Width; {PrintBorder.Right - PrintBorder.Left;}
  5620.  
  5621.   {$IFDEF WINDOWS}
  5622.   {create the metafile canvas to draw on:}
  5623.     AMetafileCanvas :=
  5624.       TMetafileCanvas.Create(AMetafile, 0);
  5625.   {$ENDIF}
  5626.   {$IFNDEF DELPHI1}
  5627.     SetMetafileDescription;
  5628.   {create the metafile canvas to draw on:}
  5629.     AMetafileCanvas :=
  5630.       TMetafileCanvas.CreateWithComment(AMetafile, 0, FCreatedBy, FDescription);
  5631.   {$ENDIF}
  5632.  
  5633.  {draw the graph on the metafile:}
  5634.     Draw(AMetafileCanvas);
  5635.     AMetafileCanvas.Free;
  5636.  
  5637. {note: the D4 TPrinter has a Copies property, but not all printers support it,
  5638.  so do printing the slow way:}
  5639.     Printer.BeginDoc;
  5640.     for i := 1 to Copies do
  5641.     begin
  5642.       if (i > 1) then
  5643.         Printer.NewPage;
  5644.       Printer.Canvas.StretchDraw(PrintBorder, AMetafile);
  5645.     end;
  5646.  
  5647.     AMetafile.Free;
  5648.     Printer.EndDoc;
  5649.     DoStyleChange(Self);
  5650.   end; {PrintDialog}
  5651.   PrintDialog.Free;
  5652. end;
  5653. {$ENDIF}
  5654. {$IFDEF LINUX}
  5655. procedure TCustomPlot.PrintClick(
  5656.   Sender: TObject);
  5657. begin
  5658.   ShowMessage('Printing not implemented yet !');
  5659. end;
  5660. {$ENDIF}
  5661.  
  5662. {------------------------------------------------------------------------------
  5663.     Procedure: TCustomPlot.ShowAllClick
  5664.   Description: Shows/reveals all screen objects
  5665.        Author: Mat Ballard
  5666.  Date created: 12/1/1999
  5667. Date modified: 02/25/2000 by Mat Ballard
  5668.       Purpose: makes everything visible.
  5669.  Known Issues:
  5670.  ------------------------------------------------------------------------------}
  5671. procedure TCustomPlot.ShowAllClick(
  5672.   Sender: TObject);
  5673. var
  5674.   i: Integer;
  5675. begin
  5676.   for i := 0 to FSeriesList.Count-1 do
  5677.     TSeries(FSeriesList[i]).Visible := TRUE;
  5678.  
  5679.   for i := 0 to ScreenObjectList.Count-1 do
  5680.     TRectangle(ScreenObjectList.Items[i]).Visible := TRUE;
  5681.  
  5682.   DoStyleChange(Self);
  5683. end;
  5684.  
  5685. {------------------------------------------------------------------------------
  5686.     Procedure: TCustomPlot.PositionClick
  5687.   Description: Where the hell are we ?
  5688.        Author: Mat Ballard
  5689.  Date created: 12/1/1999
  5690. Date modified: 02/25/2000 by Mat Ballard
  5691.       Purpose: Displays (and copies) the current mouse click position, in USER units
  5692.  Known Issues:
  5693.  ------------------------------------------------------------------------------}
  5694. procedure TCustomPlot.PositionClick(
  5695.   Sender: TObject);
  5696. var
  5697.   Msg: String;
  5698. begin
  5699.   if (Sender is TPlotMenu) then
  5700. {came via }
  5701.   begin
  5702.     ScreenJob := sjPosition;
  5703.     Screen.Cursor := crScope;
  5704.     FInstructions.Clear;
  5705.     FInstructions.Add(sPosition1);
  5706.     DoStyleChange(Self);
  5707.   end
  5708.   else
  5709.   begin
  5710.     Msg := Format(sPosition2,
  5711.       [Selection.Left, Selection.Top]) + CRLF +
  5712.         sPosition3 +
  5713.           FXAxis.LabelToStrF(FXAxis.XofF(Selection.Left));
  5714.     if (Length(FXAxis.Title.Units) > 0) then
  5715.       Msg := Msg + ' ' + FXAxis.Title.Units;
  5716.     Msg := Msg + ', ' +
  5717.       FYAxis.LabelToStrF(FYAxis.YofF(Selection.Top));
  5718.     if (Length(FYAxis.Title.Units) > 0) then
  5719.       Msg := Msg + ' ' + FYAxis.Title.Units;
  5720.     Msg := Msg + ').';
  5721.     ShowMessage(Msg);
  5722.     ClipBoard.AsText := Msg;
  5723.     ZeroScreenStuff;
  5724.   end;
  5725. end;
  5726.  
  5727. {------------------------------------------------------------------------------
  5728.     Procedure: TCustomPlot.NearestPointClick
  5729.   Description: Where the hell is it ?
  5730.        Author: Mat Ballard
  5731.  Date created: 12/1/1999
  5732. Date modified: 02/25/2000 by Mat Ballard
  5733.       Purpose: finds the nearest point of the nearest Axis
  5734.  Known Issues:
  5735.  ------------------------------------------------------------------------------}
  5736. procedure TCustomPlot.NearestPointClick(
  5737.   Sender: TObject);
  5738. var
  5739.   NearestiX,
  5740.   NearestiY: Integer;
  5741.   MinDistance: Single;
  5742.   Msg: String;
  5743. begin
  5744.   if (Sender is TPlotMenu) then
  5745. {came via }
  5746.   begin
  5747.     ScreenJob := sjNearestPoint;
  5748.     Screen.Cursor := crX;
  5749.     FInstructions.Clear;
  5750.     FInstructions.Add(sClickNear);
  5751.     DoStyleChange(Self);
  5752.   end
  5753.   else
  5754.   begin
  5755.     ThePointNumber := FSeriesList.GetNearestPoint(
  5756.       FPlotType,
  5757.       FColumnGap,
  5758.       Selection.Left, Selection.Top,
  5759.       TheSeries,
  5760.       MinDistance,
  5761.       pSeries);
  5762.     Msg := sTheNearestPointIs + IntToStr(ThePointNumber) + ' in ' +
  5763.       pSeries.Name + CRLF + sAt + ' (' +
  5764.         FXAxis.LabelToStrF(pSeries.XData^[ThePointNumber]);
  5765.     if (Length(FXAxis.Title.Units) > 0) then
  5766.       Msg := Msg + ' ' + FXAxis.Title.Units;
  5767.     Msg := Msg + ', ' +
  5768.       FYAxis.LabelToStrF(pSeries.YData^[ThePointNumber]);
  5769.     if (Length(FYAxis.Title.Units) > 0) then
  5770.       Msg := Msg + ' ' + FYAxis.Title.Units;
  5771.     Msg := Msg + ').';
  5772.     with Canvas do
  5773.     begin
  5774.       Pen.Color := clRed;
  5775.       Pen.Mode := pmNotXOR;
  5776.       Pen.Style := psSolid;
  5777.       Pen.Width := 2;
  5778.       NearestiX := pSeries.XAxis.FofX(pSeries.XData^[ThePointNumber]);
  5779.       NearestiY := pSeries.YAxis.FofY(pSeries.YData^[ThePointNumber]);
  5780.       Ellipse(NearestiX-10, NearestiY-10, NearestiX+10, NearestiY+10);
  5781.     end;
  5782.  
  5783.     ShowMessage(Msg);
  5784.     ClipBoard.AsText := Msg;
  5785.  
  5786.     with Canvas do
  5787.     begin
  5788.       {Pen.Color := clBlack;
  5789.       Pen.Mode := pmNotXOR;
  5790.       Pen.Style := psSolid;}
  5791.       Ellipse(NearestiX-10, NearestiY-10, NearestiX+10, NearestiY+10);
  5792.     end;
  5793.     ZeroScreenStuff;
  5794.   end;
  5795. end;
  5796.  
  5797. {------------------------------------------------------------------------------
  5798.     Procedure: TCustomPlot.DeleteSeriesClick
  5799.   Description: wrapper for TSeriesList.DeleteSeries
  5800.        Author: Mat Ballard
  5801.  Date created: 12/1/1999
  5802. Date modified: 02/25/2000 by Mat Ballard
  5803.       Purpose: Deletes the selected Series
  5804.  Known Issues:
  5805.  ------------------------------------------------------------------------------}
  5806. procedure TCustomPlot.DeleteSeriesClick(
  5807.   Sender: TObject);
  5808. begin
  5809.   if (GetSeriesFromUser) then
  5810.   begin
  5811.     FSeriesList.DeleteSeries(TheSeries, not(csDesigning in ComponentState));
  5812.     DoStyleChange(Self);
  5813.   end;
  5814.   ZeroScreenStuff;
  5815. end;
  5816.  
  5817. {------------------------------------------------------------------------------
  5818.     Procedure: TCustomPlot.CopySeriesClick
  5819.   Description: wrapper for TSeriesList.CopySeries
  5820.        Author: Mat Ballard
  5821.  Date created: 12/1/1999
  5822. Date modified: 02/25/2000 by Mat Ballard
  5823.       Purpose: Copies the selected Series (as text)
  5824.  Known Issues:
  5825.  ------------------------------------------------------------------------------}
  5826. procedure TCustomPlot.CopySeriesClick(
  5827.   Sender: TObject);
  5828. begin
  5829.   if (GetSeriesFromUser) then
  5830.     pSeries.CopyToClipBoard;
  5831.   ZeroScreenStuff;
  5832. end;
  5833.  
  5834. {------------------------------------------------------------------------------
  5835.     Procedure: TCustomPlot.NewSeriesClick
  5836.   Description: wrapper for TSeriesList.AddSeries
  5837.        Author: Mat Ballard
  5838.  Date created: 04/16/2001
  5839. Date modified: 04/16/2001 by Mat Ballard
  5840.       Purpose: Adds a new Series
  5841.  Known Issues:
  5842.  ------------------------------------------------------------------------------}
  5843. procedure TCustomPlot.NewSeriesClick(
  5844.   Sender: TObject);
  5845. var
  5846.   Index,
  5847.   TheNewSeries: Integer;
  5848.   pXSeries: TSeries;
  5849.   OptionsDlg: TOptionsDlg;
  5850. begin
  5851.   OptionsDlg := TOptionsDlg.Create(nil);
  5852.   with OptionsDlg do
  5853.   begin
  5854.     FormTitle := sNewSeries1;
  5855.     Question := sNewSeries2;
  5856.     OptionList.Add(sNewSeries3);
  5857.     for Index := 0 to FSeriesList.Count-1 do
  5858.       OptionList.Add(TSeries(FSeriesList.Items[Index]).Name);
  5859.  
  5860.     Index := Execute - 1;
  5861.   end;
  5862.   OptionsDlg.Free;
  5863.  
  5864.   if (Index >= 0) then
  5865.   begin
  5866.     if (Index = 0) then
  5867.     begin
  5868.       TheNewSeries := FSeriesList.Add(-1);
  5869.     end
  5870.     else
  5871.     begin
  5872.       pXSeries := TSeries(FSeriesList.Items[Index]);
  5873.       if (pXSeries.ExternalXSeries) then
  5874.         pXSeries := pXSeries.XDataSeries;
  5875.       Index := FSeriesList.IndexOf(pXSeries);
  5876.       TheNewSeries := FSeriesList.Add(Index);
  5877.     end;
  5878.     TSeries(FSeriesList.Items[TheNewSeries]).EditData(FHelpFile);
  5879.   end;
  5880.   ZeroScreenStuff;
  5881. end;
  5882.  
  5883. {------------------------------------------------------------------------------
  5884.     Procedure: TCustomPlot.CloneSeriesClick
  5885.   Description: wrapper for TSeriesList.CloneSeries
  5886.        Author: Mat Ballard
  5887.  Date created: 12/1/1999
  5888. Date modified: 02/25/2000 by Mat Ballard
  5889.       Purpose: Clones the selected Series
  5890.  Known Issues:
  5891.  ------------------------------------------------------------------------------}
  5892. procedure TCustomPlot.CloneSeriesClick(
  5893.   Sender: TObject);
  5894. begin
  5895.   if (GetSeriesFromUser) then
  5896.   begin
  5897.     FSeriesList.CloneSeries(TheSeries);
  5898.     DoStyleChange(Self);
  5899.   end;
  5900.   ZeroScreenStuff;
  5901. end;
  5902.  
  5903. {------------------------------------------------------------------------------
  5904.     Procedure: TCustomPlot.ModeClick
  5905.   Description: Changes how the graph appears and reacts to new data
  5906.        Author: Mat Ballard
  5907.  Date created: 12/1/1999
  5908. Date modified: 02/25/2000 by Mat Ballard
  5909.       Purpose: sets the DisplayMode property
  5910.  Known Issues:
  5911.  ------------------------------------------------------------------------------}
  5912. procedure TCustomPlot.ModeClick(
  5913.   Sender: TObject);
  5914. var
  5915.   Index: Integer;
  5916.   DisplayHistoryStr: String;
  5917.   OptionsDlg: TOptionsDlg;
  5918. begin
  5919.   OptionsDlg := TOptionsDlg.Create(nil);
  5920.   with OptionsDlg do
  5921.   begin
  5922.     FormTitle := sMode1;
  5923.     Question := sMode2;
  5924.     OptionList.Add(sMode3);
  5925.     OptionList.Add(sMode4);
  5926.     OptionList.Add(sMode5);
  5927.     OptionList.Add(sMode6);
  5928.     Index := Execute - 1;
  5929.   end;
  5930.   OptionsDlg.Free;
  5931.  
  5932.   if (Index >= 0) then
  5933.   begin
  5934.     if (Index = Ord(dmHistory)) then
  5935.     begin
  5936.       DisplayHistoryStr := FloatToStr(FDisplayHistory);
  5937.       if (InputQuery(sHistoryRange, '', DisplayHistoryStr)) then
  5938.       FDisplayHistory := StrToFloat(DisplayHistoryStr);
  5939.     end;
  5940.     SetDisplayMode(TDisplayMode(Index));
  5941.   end;
  5942. end;
  5943.  
  5944. {------------------------------------------------------------------------------
  5945.     Procedure: TCustomPlot.CanPaste
  5946.   Description: Can we paste data from the Clipboard into TPlot ?
  5947.        Author: Mat Ballard
  5948.  Date created: 11/28/1999
  5949. Date modified: 11/28/2000 by Mat Ballard
  5950.       Purpose: check in with the clipboard, looking for text data
  5951.  Known Issues:
  5952.  ------------------------------------------------------------------------------}
  5953. function TCustomPlot.CanPaste: Boolean;
  5954. {$IFDEF LINUX}
  5955. var
  5956.   FormatList: TStringList;
  5957.   i: Integer;
  5958. {$ENDIF}
  5959. begin
  5960. {$IFDEF MSWINDOWS}
  5961.   CanPaste := (ClipBoard.HasFormat(CF_TEXT));
  5962. {$ENDIF}
  5963. {$IFDEF LINUX}
  5964.   CanPaste := FALSE;
  5965.   FormatList := TStringList.Create;
  5966.   Clipboard.SupportedFormats(FormatList);
  5967.   for i := 0 to FormatList.Count-1 do
  5968.   begin
  5969.     if (Pos('text/plain', FormatList.Strings[i]) > 0) then
  5970.     begin
  5971.       CanPaste := TRUE;
  5972.       exit;
  5973.     end;
  5974.   end;
  5975.   FormatList.Free;
  5976. {$ENDIF}
  5977. end;
  5978.  
  5979. {------------------------------------------------------------------------------
  5980.     Procedure: TCustomPlot.PasteSeriesClick
  5981.   Description: Pastes data from the Clipboard
  5982.        Author: Mat Ballard
  5983.  Date created: 12/1/1999
  5984. Date modified: 02/25/2000 by Mat Ballard
  5985.       Purpose: Collects the data from the Clipboard and runs the ParseData method on it.
  5986.  Known Issues: limited to 32 K under D1. Can be fixed with messy memory management.
  5987.  ------------------------------------------------------------------------------}
  5988. procedure TCustomPlot.PasteClick(
  5989.   Sender: TObject);
  5990. var
  5991.   TheData: TStringList;
  5992. {$IFDEF DELPHI1}
  5993.   LongStr: PChar;
  5994. {$ENDIF}
  5995. begin
  5996.   TheData := TStringList.Create;
  5997. {$IFDEF DELPHI1}
  5998.   GetMem(LongStr, 32767);
  5999.   Clipboard.GetTextBuf(LongStr, 32767);
  6000.   TheData.SetText(LongStr);
  6001.   FreeMem(LongStr, 32767);
  6002. {$ELSE}
  6003.   TheData.Text := Clipboard.AsText;
  6004. {$ENDIF}
  6005.   FSeriesList.ParseData(TheData, FHelpFile);
  6006.   TheData.Free;
  6007.  
  6008.   ZoomOutClick(Self);
  6009. end;
  6010.  
  6011. {------------------------------------------------------------------------------
  6012.     Procedure: TCustomPlot.LineBestFitClick
  6013.   Description: Initiates a Line of Best Fit.
  6014.        Author: Mat Ballard
  6015.  Date created: 12/1/1999
  6016. Date modified: 05/30/2001 by Mat Ballard
  6017.       Purpose: Sets the Instructions and the ScreenJob
  6018.  Known Issues:
  6019.  ------------------------------------------------------------------------------}
  6020. procedure TCustomPlot.LineBestFitClick(
  6021.   Sender: TObject);
  6022. var
  6023. {Variables used in least-squares fitting:}
  6024.   NoLeastSquarePts: Integer;
  6025.   SumX, SumY, SumXsq, SumXY, SumYsq: Double;
  6026.   Rsq: Single;
  6027. {  Slope, Intercept: Single; - are globals to allow drawing of line}
  6028.  
  6029.   procedure InitializeFit;
  6030.   begin
  6031. {Initialize the fit parameters:}
  6032.     NoLeastSquarePts := 0;
  6033.     SumX := 0;
  6034.     SumY := 0;
  6035.     SumXsq := 0;
  6036.     SumXY := 0;
  6037.     SumYsq := 0;
  6038.   end;
  6039.   
  6040. begin
  6041.   if (GetSeriesFromUser) then
  6042.   begin
  6043.     if ((FScreenJob = sjRightDrag) or
  6044.         (FScreenJob = sjLineOfBestFit)) then
  6045.     begin
  6046.       InitializeFit;
  6047.       pSeries.LineBestFit(XAxis.XofF(Selection.Left), XAxis.XofF(Selection.Right),
  6048.         NoLeastSquarePts,
  6049.         SumX, SumY, SumXsq, SumXY, SumYsq,
  6050.         Slope, Intercept, Rsq);
  6051.       SetResult(Slope, Intercept, Rsq);
  6052.       ZeroScreenStuff;
  6053.     end
  6054.     else if (FScreenJob = sjDualLineBestFit2) then
  6055.     begin
  6056.       InitializeFit;
  6057.       pSeries.LineBestFit(XAxis.XofF(Sel1.Left), XAxis.XofF(Sel1.Right),
  6058.         NoLeastSquarePts,
  6059.         SumX, SumY, SumXsq, SumXY, SumYsq,
  6060.         Slope, Intercept, Rsq);
  6061.       pSeries.LineBestFit(XAxis.XofF(Selection.Left), XAxis.XofF(Selection.Right),
  6062.         NoLeastSquarePts,
  6063.         SumX, SumY, SumXsq, SumXY, SumYsq,
  6064.         Slope, Intercept, Rsq);
  6065.       SetResult(Slope, Intercept, Rsq);
  6066.       ZeroScreenStuff;
  6067.     end
  6068.     else
  6069.     begin
  6070.       FInstructions.Clear;
  6071.       FInstructions.Add(sLBF);
  6072.       ScreenJob := sjLineOfBestFit;
  6073.       FResult.Visible := False;
  6074.       DoStyleChange(Self);
  6075.     end;
  6076.   end;
  6077. end;
  6078.  
  6079. {------------------------------------------------------------------------------
  6080.     Procedure: TCustomPlot.TwoRegionLineBestFitClick
  6081.   Description: Initiates a Two Region Line of Best Fit.
  6082.        Author: Mat Ballard
  6083.  Date created: 12/1/1999
  6084. Date modified: 05/30/2001 by Mat Ballard
  6085.       Purpose: Sets the FInstructions and the ScreenJob
  6086.  Known Issues:
  6087.  ------------------------------------------------------------------------------}
  6088. procedure TCustomPlot.TwoRegionLineBestFitClick(Sender: TObject);
  6089. begin
  6090.   if (GetSeriesFromUser) then
  6091.   begin
  6092.     if ((FScreenJob = sjRightDrag) or
  6093.         (FScreenJob = sjDualLineBestFit1)) then
  6094.     begin
  6095.       Sel1.Left := Selection.Left;
  6096.       Sel1.Top := Selection.Top;
  6097.       Sel1.Right := Selection.Right;
  6098.       Sel1.Bottom := Selection.Bottom;
  6099.       ScreenJob := sjDualLineBestFit2;
  6100.       FInstructions.Clear;
  6101.       FInstructions.Add(sDualInstruction + sFit);
  6102.       DoStyleChange(Self);
  6103.     end
  6104.     else
  6105.     begin
  6106.       FInstructions.Clear;
  6107.       FInstructions.Add(s2RLBF);
  6108.       ScreenJob := sjDualLineBestFit1;
  6109.       FResult.Visible := False;
  6110.       DoStyleChange(Self);
  6111.     end;
  6112.   end;
  6113. end;
  6114.  
  6115. {$IFDEF FUNCTIONS}
  6116. {------------------------------------------------------------------------------
  6117.     Procedure: TCustomPlot.FunctionClick
  6118.   Description: Creates a new series which is a function of existing series
  6119.        Author: Mat Ballard
  6120.  Date created: 04/03/2001
  6121. Date modified: 04/03/2001 by Mat Ballard
  6122.       Purpose: data manipulation
  6123.  Known Issues:
  6124.  ------------------------------------------------------------------------------}
  6125. procedure TCustomPlot.FunctionClick(Sender: TObject);
  6126. begin
  6127.   FSeriesList.FunctionSeries;
  6128.   ZoomOutClick(Self);
  6129. end;
  6130. {$ENDIF}
  6131.  
  6132. {------------------------------------------------------------------------------
  6133.     Procedure: TCustomPlot.SmoothSeriesClick
  6134.   Description: Smoothes the selected data Series
  6135.        Author: Mat Ballard
  6136.  Date created: 12/1/1999
  6137. Date modified: 02/25/2000 by Mat Ballard
  6138.       Purpose: Obtains the Smoothing Order then runs the selected Series' Smooth method
  6139.  Known Issues:
  6140.  ------------------------------------------------------------------------------}
  6141. procedure TCustomPlot.SmoothSeriesClick(
  6142.   Sender: TObject);
  6143. var
  6144.   SmoothOrder: Integer;
  6145.   SmoothStr: String;
  6146. begin
  6147.   if (GetSeriesFromUser) then
  6148.   begin
  6149.     SmoothStr := '10';
  6150.     if (InputQuery(sSmoothing1 + pSeries.Name,
  6151.                    sSmoothing2,
  6152.                    SmoothStr)) then
  6153.     begin
  6154.       try
  6155.         SmoothOrder := StrToInt(SmoothStr);
  6156.         pSeries.Smooth(SmoothOrder);
  6157.         DoStyleChange(Self);
  6158.       except
  6159.         ShowMessage(sSmoothFail);
  6160.       end;
  6161.     end;
  6162.   end;
  6163.   ZeroScreenStuff;
  6164. end;
  6165.  
  6166. {------------------------------------------------------------------------------
  6167.     Procedure: TCustomPlot.SortClick
  6168.   Description: sorts the selected data
  6169.        Author: Mat Ballard
  6170.  Date created: 04/25/2000
  6171. Date modified: 04/25/2000 by Mat Ballard
  6172.       Purpose: data management and manipulation
  6173.  Known Issues:
  6174.  ------------------------------------------------------------------------------}
  6175. procedure TCustomPlot.SortClick(Sender: TObject);
  6176. begin
  6177.   if (GetSeriesFromUser) then
  6178.   begin
  6179.     pSeries.Sort;
  6180.     DoStyleChange(Self);
  6181.   end;
  6182.   ZeroScreenStuff;
  6183. end;
  6184.  
  6185. procedure TCustomPlot.SplineClick(Sender: TObject);
  6186. begin
  6187.   if (GetSeriesFromUser) then
  6188.   begin
  6189.     Self.Spline(TheSeries);
  6190.     DoStyleChange(Self);
  6191.   end;
  6192.   ZeroScreenStuff;
  6193. end;
  6194.  
  6195. {------------------------------------------------------------------------------
  6196.      Function: TCustomPlot.Spline
  6197.   Description: wrapper for TSeriesList.Spline
  6198.        Author: Mat Ballard
  6199.  Date created: 12/1/1999
  6200. Date modified: 02/25/2000 by Mat Ballard
  6201.       Purpose: Adds a new, empty data Series to the graph
  6202.  Known Issues:
  6203.  ------------------------------------------------------------------------------}
  6204. function TCustomPlot.Spline(ASeries: Integer): Integer;
  6205. var
  6206.   Density: Word;
  6207.   pSplineSeries: TSeries;
  6208.   TheString: String;
  6209. begin
  6210.   Spline := -1;
  6211. {if it isn't already ...}
  6212.   pSeries := TSeries(FSeriesList.Items[ASeries]);
  6213.  
  6214.   TheString := '1';
  6215.   if (InputQuery(sSpline1, sSpline2, TheString)) then
  6216.   begin
  6217.     Density := StrToInt(TheString);
  6218.  
  6219.     ASeries := FSeriesList.Add(-1);
  6220.     pSplineSeries := TSeries(FSeriesList.Items[ASeries]);
  6221.     pSplineSeries.AllocateNoPts(pSeries.NoPts * (Density + 1));
  6222.  
  6223.     pSeries.DoSpline(Density, pSplineSeries);
  6224.  
  6225.     pSplineSeries.Name := sSpline3 + pSeries.Name;
  6226.     pSplineSeries.Pen.Style := psDot;
  6227.     pSplineSeries.Visible := TRUE;
  6228.     Spline := ASeries;
  6229. {should we call pSeries.ClearSpline ?}
  6230.     DoStyleChange(Self);
  6231.   end;
  6232. end;
  6233.  
  6234. {------------------------------------------------------------------------------
  6235.     Procedure: TCustomPlot.CompressSeriesClick
  6236.   Description: Reduces the number of data points of the selected Series by averaging the data
  6237.        Author: Mat Ballard
  6238.  Date created: 10/15/2000
  6239. Date modified: 10/15/2000 by Mat Ballard
  6240.       Purpose: data management and manipulation
  6241.  Known Issues:
  6242.  ------------------------------------------------------------------------------}
  6243. procedure TCustomPlot.CompressSeriesClick(
  6244.   Sender: TObject);
  6245. var
  6246.   CompressRatio: Integer;
  6247.   CompressStr: String;
  6248. begin
  6249.   if (GetSeriesFromUser) then
  6250.   begin
  6251.     if (pSeries.XDataRefCount > 0) then raise
  6252.       EComponentError.CreateFmt(
  6253.         sCompress1 + CRLF + sCompress2,
  6254.         [pSeries.Name, pSeries.XDataRefCount]);
  6255.  
  6256.     if (pSeries.ExternalXSeries) then raise
  6257.       EComponentError.CreateFmt(
  6258.         sCompress1 + CRLF + sCompress3,
  6259.         [pSeries.Name, pSeries.XDataSeries.Name]);
  6260.  
  6261.     CompressStr := '10';
  6262.     if (InputQuery(sCompress4 + pSeries.Name,
  6263.                    sCompress5,
  6264.                    CompressStr)) then
  6265.     begin
  6266.       try
  6267.         CompressRatio := StrToInt(CompressStr);
  6268.         pSeries.Compress(CompressRatio);
  6269.       except
  6270.         ShowMessage(sCompress6);
  6271.       end;
  6272.     end;
  6273.     DoStyleChange(Self);
  6274.   end;
  6275.   ZeroScreenStuff;
  6276. end;
  6277.  
  6278. {------------------------------------------------------------------------------
  6279.     Procedure: TCustomPlot.CompressAllSeriesClick
  6280.   Description: Reduces the number of data points in ALL Series by averaging the data
  6281.        Author: Mat Ballard
  6282.  Date created: 10/15/2000
  6283. Date modified: 10/15/2000 by Mat Ballard
  6284.       Purpose: data management and manipulation
  6285.  Known Issues:
  6286.  ------------------------------------------------------------------------------}
  6287. procedure TCustomPlot.CompressAllSeriesClick(
  6288.   Sender: TObject);
  6289. var
  6290.   CompressRatio: Integer;
  6291.   CompressStr: String;
  6292.   i: Integer;
  6293. begin
  6294.   CompressStr := '10';
  6295.   if (InputQuery(sCompressAll1,
  6296.                  sCompress5,
  6297.                  CompressStr)) then
  6298.   begin
  6299.     try
  6300.       CompressRatio := StrToInt(CompressStr);
  6301.       for i := 0 to FSeriesList.Count-1 do
  6302.         TSeries(FSeriesList.Items[i]).Compress(CompressRatio);
  6303.     except
  6304.       ShowMessage(sCompress6);
  6305.     end;
  6306.   end;
  6307.   DoStyleChange(Self);
  6308. end;
  6309.  
  6310. {------------------------------------------------------------------------------
  6311.     Procedure: TCustomPlot.ContractSeriesClick
  6312.   Description: Reduces the number of data points of the selected Series by throwing away the ends
  6313.        Author: Mat Ballard
  6314.  Date created: 12/1/1999
  6315. Date modified: 05/30/2001 by Mat Ballard
  6316.       Purpose: data management and manipulation
  6317.  Known Issues:
  6318.  ------------------------------------------------------------------------------}
  6319. procedure TCustomPlot.ContractSeriesClick(
  6320.   Sender: TObject);
  6321. var
  6322.   TheLeft,
  6323.   TheRight: Integer;
  6324. begin
  6325.   if (GetSeriesFromUser) then
  6326.   begin
  6327.     if (pSeries.XDataRefCount > 0) then raise
  6328.       EComponentError.CreateFmt(
  6329.         sContract1 + CRLF + sCompress2,
  6330.         [pSeries.Name, pSeries.XDataRefCount]);
  6331.  
  6332.     if (pSeries.ExternalXSeries) then raise
  6333.       EComponentError.CreateFmt(
  6334.         sContract1 + CRLF + sCompress3,
  6335.         [pSeries.Name, pSeries.XDataSeries.Name]);
  6336.  
  6337.     if ((FScreenJob = sjRightDrag) or
  6338.         (FScreenJob = sjContractSeries)) then
  6339.     begin
  6340.       TheLeft := pSeries.GetNearestPointToFX(Selection.Left);
  6341.       TheRight := pSeries.GetNearestPointToFX(Selection.Right);
  6342.       pSeries.Contract(TheLeft, TheRight);
  6343.       ZeroScreenStuff;
  6344.     end
  6345.     else
  6346.     begin
  6347.       FScreenJob := sjContractSeries;
  6348.       FInstructions.Clear;
  6349.       FInstructions.Add(sContract2);
  6350.       FInstructions.Add(sContract3);
  6351.       DoStyleChange(Self);
  6352.     end;
  6353.     DoStyleChange(Self);
  6354.   end;
  6355. end;
  6356.  
  6357. {------------------------------------------------------------------------------
  6358.     Procedure: TCustomPlot.ContractAllSeriesClick
  6359.   Description: Reduces the number of data points of the selected Series by throwing away the ends
  6360.        Author: Mat Ballard
  6361.  Date created: 12/1/1999
  6362. Date modified: 05/30/2001 by Mat Ballard
  6363.       Purpose: data management and manipulation
  6364.  Known Issues:
  6365.  ------------------------------------------------------------------------------}
  6366. procedure TCustomPlot.ContractAllSeriesClick(
  6367.   Sender: TObject);
  6368. var
  6369.   TheLeft,
  6370.   TheRight: Integer;
  6371.   i: Integer;
  6372. begin
  6373.   if ((FScreenJob = sjRightDrag) or
  6374.      (FScreenJob = sjContractAllSeries)) then
  6375.   begin
  6376.     TheLeft := TSeries(FSeriesList.Items[0]).GetNearestPointToFX(Selection.Left);
  6377.     TheRight := TSeries(FSeriesList.Items[0]).GetNearestPointToFX(Selection.Right);
  6378.     for i := 0 to FSeriesList.Count-1 do
  6379.       TSeries(FSeriesList.Items[i]).Contract(TheLeft, TheRight);
  6380.     ZeroScreenStuff;
  6381.   end
  6382.   else
  6383.   begin
  6384.     FScreenJob := sjContractAllSeries;
  6385.     FInstructions.Clear;
  6386.     FInstructions.Add(sContract2);
  6387.     FInstructions.Add(sContract3);
  6388.     DoStyleChange(Self);
  6389.   end;
  6390.   DoStyleChange(Self);
  6391. end;
  6392.  
  6393. {------------------------------------------------------------------------------
  6394.     Procedure: TCustomPlot.LegendClick
  6395.   Description: Sets the Legend Direction
  6396.        Author: Mat Ballard
  6397.  Date created: 12/1/1999
  6398. Date modified: 02/25/2000 by Mat Ballard
  6399.       Purpose:
  6400.  Known Issues:
  6401.  ------------------------------------------------------------------------------}
  6402. procedure TCustomPlot.LegendClick(
  6403.   Sender: TObject);
  6404. var
  6405.   Index: Integer;
  6406.   OptionsDlg: TOptionsDlg;
  6407. begin
  6408.   OptionsDlg := TOptionsDlg.Create(nil);
  6409.   with OptionsDlg do
  6410.   begin
  6411.     FormTitle := sLegend1;
  6412.     Question := sLegend2;
  6413.     OptionList.Add(sHorizontally);
  6414.     OptionList.Add(sVertically);
  6415.     Index := Execute - 1;
  6416.   end;
  6417.   OptionsDlg.Free;
  6418.  
  6419.   if (Index >= 0) then
  6420.   begin
  6421.     FLegend.Direction := TDirection(Index);
  6422.   end;
  6423.   ZeroScreenStuff;
  6424.   DoStyleChange(Self);
  6425. end;
  6426.  
  6427. {------------------------------------------------------------------------------
  6428.     Procedure: TCustomPlot.EditAxisClick
  6429.   Description: Runs the Axis Editor of the selected Axis
  6430.        Author: Mat Ballard
  6431.  Date created: 12/1/1999
  6432. Date modified: 06/28/2000 by Mat Ballard
  6433.       Purpose:
  6434.  Known Issues:
  6435.  ------------------------------------------------------------------------------}
  6436. procedure TCustomPlot.EditAxisClick(
  6437.   Sender: TObject);
  6438. var
  6439.   i: Integer;
  6440.   AxisEditor: TAxisEditorForm;
  6441.   AXP: TAxisProperty;
  6442. begin
  6443.   if (GetAxisFromUser(0)) then
  6444.   begin
  6445.     AxisEditor := TAxisEditorForm.Create(nil);
  6446.     AxisEditor.ThePlot := TObject(Self);
  6447.  
  6448.     if (FDisplayMode = dmHistory) then
  6449.       AxisEditor.HistoryMode := TRUE;
  6450.  
  6451. {Iterate over all axes:}
  6452.     for i := 0 to FAxisList.Count-1 do
  6453.     begin
  6454.       pAxis := TAxis(FAxisList.Items[i]);
  6455.       AXP.LabelFormat := pAxis.Labels.NumberFormat;
  6456.       AXP.LabelDigits := pAxis.Labels.Digits;
  6457.       AXP.LabelPrecision := pAxis.Labels.Precision;
  6458.       AXP.LabelDirection := pAxis.Labels.Direction;
  6459.       AXP.PenColor := pAxis.Pen.Color;
  6460.       AXP.PenWidthIndex := pAxis.Pen.Width;
  6461.       AXP.PenStyleIndex := Ord(pAxis.Pen.Style);
  6462.       AXP.TickSize := pAxis.TickSize;
  6463.       AXP.TickDirection := pAxis.TickDirection;
  6464.       AXP.TickStepSize := pAxis.StepSize;
  6465.       AXP.TickMinors := pAxis.TickMinor;
  6466.       AXP.ScaleMin := pAxis.Min;
  6467.       AXP.ScaleMax := pAxis.Max;
  6468.       AXP.ScaleIntercept := pAxis.Intercept;
  6469.       AXP.ScaleAuto := pAxis.AutoScale;
  6470.       AXP.ScaleLog := pAxis.LogScale;
  6471.       AXP.ArrowSize := pAxis.ArrowSize;
  6472.       AXP.ArrowDirection := pAxis.Alignment;
  6473.       AXP.Visible := pAxis.Visible;
  6474.       if (TObject(FAxisList.Items[i]) is TAngleAxis) then
  6475.       begin
  6476.         AXP.ZAngle := TAngleAxis(pAxis).Angle;
  6477.         AXP.ZLength := TAngleAxis(pAxis).Length;
  6478.       end
  6479.       else
  6480.       begin
  6481.         AXP.ZAngle := 0;
  6482.         AXP.ZLength := 0;
  6483.       end;
  6484.       AxisEditor.AddAxis(pAxis.Title.Caption, AXP);
  6485.     end;
  6486.  
  6487.     if (TheAxis >= 0) then
  6488.       AxisEditor.NoComboBox.ItemIndex := TheAxis;
  6489.     AxisEditor.SelectAxis(TheAxis);
  6490.     AxisEditor.HelpFile := FHelpFile;
  6491.  
  6492.     if (AxisEditor.ShowModal = mrOK) then
  6493.       ApplyAxisChange(AxisEditor);
  6494.  
  6495.     AxisEditor.Free;
  6496.  
  6497.     ZeroScreenStuff;
  6498.   end; {GetAxisFrom User}
  6499. end;
  6500.  
  6501. {------------------------------------------------------------------------------
  6502.     Procedure: TCustomPlot.ApplyAxisChange
  6503.   Description: This applies changes from the PropertiesDialog.
  6504.        Author: Mat Ballard
  6505.  Date created: 03/28/2001
  6506. Date modified: 03/28/2001 by Mat Ballard
  6507.       Purpose: User interface management
  6508.  Known Issues:
  6509.  ------------------------------------------------------------------------------}
  6510. procedure TCustomPlot.ApplyAxisChange(Sender: TObject);
  6511. var
  6512.   i: Integer;
  6513.   pAXP: ^TAxisProperty;
  6514. begin
  6515.   for i := 0 to FAxisList.Count-1 do
  6516.   begin
  6517.     pAXP := TAxisEditorForm(Sender).AxisPropertyList.Items[i];
  6518.     pAxis := TAxis(FAxisList.Items[i]);
  6519.     pAxis.Title.Caption := TAxisEditorForm(Sender).AxisNames.Strings[i];
  6520.     pAxis.Labels.NumberFormat := pAXP^.LabelFormat;
  6521.     pAxis.Labels.Digits := pAXP^.LabelDigits;
  6522.     pAxis.Labels.Precision := pAXP^.LabelPrecision;
  6523.     pAxis.Labels.Direction := pAXP^.LabelDirection;
  6524.     pAxis.Pen.Color := pAXP^.PenColor;
  6525.     pAxis.Pen.Width := pAXP^.PenWidthIndex;
  6526.     pAxis.Pen.Style := TPenStyle(pAXP^.PenStyleIndex);
  6527.     pAxis.TickSize := pAXP^.TickSize;
  6528.     pAxis.TickDirection := pAXP^.TickDirection;
  6529.     pAxis.TickMinor := pAXP^.TickMinors;
  6530.     pAxis.AutoScale := pAXP^.ScaleAuto;
  6531.     pAxis.StepSize := pAXP^.TickStepSize;
  6532.     pAxis.Min := pAXP^.ScaleMin;
  6533.     pAxis.Max := pAXP^.ScaleMax;
  6534.     pAxis.Intercept := pAXP^.ScaleIntercept;
  6535.     pAxis.LogScale := pAXP^.ScaleLog;
  6536.     pAxis.ArrowSize := pAXP^.ArrowSize;
  6537.     pAxis.Alignment := pAXP^.ArrowDirection;
  6538.     if (TObject(FAxisList.Items[i]) is TAngleAxis) then
  6539.     begin
  6540.       TAngleAxis(pAxis).Angle := pAXP^.ZAngle;
  6541.       TAngleAxis(pAxis).Length := pAXP^.ZLength;
  6542.     end;
  6543.     pAxis.Visible := pAXP^.Visible;
  6544.     pAxis.ReScale;
  6545.   end; {for}
  6546.   {DoStyleChange(Self);}
  6547. end;
  6548.  
  6549. {------------------------------------------------------------------------------
  6550.     Procedure: TCustomPlot.NewNoteClick
  6551.   Description: Creates a new note
  6552.        Author: Mat Ballard
  6553.  Date created: 11/1/2000
  6554. Date modified: 11/1/2000 by Mat Ballard
  6555.       Purpose: appearance management
  6556.  Known Issues:
  6557.  ------------------------------------------------------------------------------}
  6558. procedure TCustomPlot.NewNoteClick(Sender: TObject);
  6559. var
  6560.   ANote: TNote;
  6561. begin
  6562.   ANote := TNote.Create(Self);
  6563.   ANote.Left := Selection.Left;
  6564.   ANote.Top := Selection.Top;
  6565.   ANote.ArrowLeft := Selection.Left + 1;
  6566.   ANote.ArrowTop := Selection.Top + 1;
  6567.   ANote.Tag := Ord(soNote);
  6568.  
  6569.   ScreenObjectList.Add(ANote);
  6570.   Inc(NoteCount);
  6571.   //NoteList.Add(ANote);
  6572.   pClickedObject := ANote;
  6573.   Screen.Cursor := crScope;
  6574.   ScreenJob := sjMoveNotePointer;
  6575.   FInstructions.Clear;
  6576.   FInstructions.Add(sNewNote1);
  6577.   DoStyleChange(Self);
  6578. end;
  6579.  
  6580. {------------------------------------------------------------------------------
  6581.     Procedure: TCustomPlot.DeleteNoteClick
  6582.   Description: Moves a note pointer
  6583.        Author: Mat Ballard
  6584.  Date created: 11/22/2000
  6585. Date modified: 11/22/2000 by Mat Ballard
  6586.       Purpose: appearance management
  6587.  Known Issues:
  6588.  ------------------------------------------------------------------------------}
  6589. procedure TCustomPlot.MoveNotePointerClick(Sender: TObject);
  6590. begin
  6591.   if (GetNoteFromUser) then
  6592.     FScreenJob := sjMoveNotePointer;
  6593. end;
  6594.  
  6595. {------------------------------------------------------------------------------
  6596.     Procedure: TCustomPlot.DeleteNoteClick
  6597.   Description: Deletes a note
  6598.        Author: Mat Ballard
  6599.  Date created: 11/14/2000
  6600. Date modified: 11/14/2000 by Mat Ballard
  6601.       Purpose: appearance management
  6602.  Known Issues:
  6603.  ------------------------------------------------------------------------------}
  6604. procedure TCustomPlot.DeleteNoteClick(Sender: TObject);
  6605. begin
  6606.   if (GetNoteFromUser) then
  6607.   begin
  6608.     ScreenObjectList.Remove(pClickedObject);
  6609.     Dec(NoteCount);
  6610.     TNote(pClickedObject).Free;
  6611.     DoStyleChange(Self);
  6612.   end;
  6613.   ZeroScreenStuff;
  6614. end;
  6615.  
  6616. {------------------------------------------------------------------------------
  6617.     Procedure: TCustomPlot.EditFontClick
  6618.   Description: Edits the font of the selected Axis
  6619.        Author: Mat Ballard
  6620.  Date created: 12/1/1999
  6621. Date modified: 02/25/2000 by Mat Ballard
  6622.       Purpose: Runs the Font common Dialog box, and applies the results to the selected object
  6623.  Known Issues:
  6624.  ------------------------------------------------------------------------------}
  6625. procedure TCustomPlot.EditFontClick(
  6626.   Sender: TObject);
  6627. var
  6628.   TheFont: TFont;
  6629.   FontDialog: TFontDialog;
  6630.   OptionsDlg: TOptionsDlg;
  6631.   TheResult: Integer;
  6632. begin
  6633. {has the user already selected an object ?}
  6634.   if ((ClickedObjectType = soNone) or
  6635.       (ClickedObjectType = soXAxis) or
  6636.       (ClickedObjectType = soYAxis) or
  6637.       (ClickedObjectType = soLeftBorder) or
  6638.       (ClickedObjectType = soTopBorder) or
  6639.       (ClickedObjectType = soRightBorder) or
  6640.       (ClickedObjectType = soBottomBorder)) then
  6641.   begin
  6642. {get the user to select an object:}
  6643.     OptionsDlg := TOptionsDlg.Create(nil);
  6644.     with OptionsDlg do
  6645.     begin
  6646.       FormTitle := sEditFont1;
  6647.       Question := sEditFont2;
  6648.       OptionList.Add(sEditFont3);
  6649.       OptionList.Add(sEditFont4);
  6650.       OptionList.Add(sEditFont5);
  6651.       OptionList.Add(sEditFont6);
  6652.       OptionList.Add(sEditFont7);
  6653.       OptionList.Add(sEditFont8);
  6654.       OptionList.Add(sEditFont9);
  6655.       OptionList.Add(sEditFont10);
  6656.       OptionList.Add(sEditFont11);
  6657.  
  6658.       TheResult := Execute;
  6659.       case TheResult of
  6660.         1: ClickedObjectType := soTitle;
  6661.         2: ClickedObjectType := soXAxisTitle;
  6662.         3: ClickedObjectType := soYAxisTitle;
  6663.         5: ClickedObjectType := soXAxisLabel;
  6664.         6: ClickedObjectType := soYAxisLabel;
  6665.         8: ClickedObjectType := soLegend;
  6666.         9: ClickedObjectType := soResult;
  6667.       end;
  6668.     end;
  6669.     OptionsDlg.Free;
  6670.   end; {if object selected}
  6671.  
  6672.   FontDialog := TFontDialog.Create(Self);
  6673.  
  6674.   case ClickedObjectType of
  6675.     soTitle: TheFont := FTitle.Font;
  6676.     soXAxisTitle: TheFont := FXAxis.Title.Font;
  6677.     soYAxisTitle: TheFont := TTitle(pClickedObject).Font;
  6678.     soXAxisLabel: TheFont := FXAxis.Labels.Font;
  6679.     soYAxisLabel: TheFont := TAxisLabel(pClickedObject).Font;
  6680.     soLegend: TheFont := FLegend.Font;
  6681.     soResult: TheFont := FResult.Font;
  6682.     soNote: TheFont := TNote(pClickedObject).Font;
  6683.   else
  6684. {assign TheFont:}
  6685.     //TheFont := nil;
  6686.     FontDialog.Free;
  6687. {don't like bugging out here, but is most elegant solution:}
  6688.     exit;
  6689.   end;
  6690.   FontDialog.Font.Assign(TheFont);
  6691.  
  6692.   if (FontDialog.Execute) then
  6693.   begin
  6694.     TheFont.Assign(FontDialog.Font);
  6695.     DoStyleChange(Self);
  6696.   end;
  6697.  
  6698.   ZeroScreenStuff;
  6699.   FontDialog.Free;
  6700. end;
  6701.  
  6702. {------------------------------------------------------------------------------
  6703.     Procedure: TCustomPlot.EditPropertiesClick
  6704.   Description: Edits the other properties of the Plot
  6705.        Author: Mat Ballard
  6706.  Date created: 10/10/2000
  6707. Date modified: 10/10/2000 by Mat Ballard
  6708.       Purpose: Runs the Properties Dialog box, and applies the results to the selected objects
  6709.  Known Issues:
  6710.  ------------------------------------------------------------------------------}
  6711. procedure TCustomPlot.EditPropertiesClick(
  6712.   Sender: TObject);
  6713. var
  6714.   PlotPropertyEditor: TPlotPropertyEditorForm;
  6715. begin
  6716.   PlotPropertyEditor := TPlotPropertyEditorForm.Create(nil);
  6717.   PlotPropertyEditor.ThePlot := TObject(Self);
  6718.   PlotPropertyEditor.HelpFile := FHelpFile;
  6719.  
  6720.   with PlotPropertyEditor do
  6721.   begin
  6722.     PlotTypeComboBox.ItemIndex := Ord(FPlotType);
  6723.     BackColorEdit.Color := Self.Color;
  6724.     BackColorEdit.Text := ColorToString(Self.Color);
  6725.     BubbleSizeNEdit.AsInteger := FBubbleSize;
  6726.     ClickAndDragDelayNEdit.AsInteger := MouseTimer.Interval;
  6727.     ColumnGapNEdit.AsInteger := FColumnGap;
  6728.     ContourDetailComboBox.ItemIndex := Ord(ContourDetail);
  6729.     GridComboBox.ItemIndex := Ord(FGrid);
  6730.     GridStyleComboBox.ItemIndex := Ord(FGridStyle);
  6731.     LinkZSeriesCheckBox.Checked := FZLink;
  6732.     MultiplicityComboBox.ItemIndex := FMultiplicity - 1;
  6733.     MultiJoinEdit.Text := GetMultiJoin;
  6734.     PenColorEdit.SetColour(FMultiplePen.Color);
  6735.     PenWidthComboBox.ItemIndex := FMultiplePen.Width;
  6736.     PenStyleComboBox.ItemIndex := Ord(FMultiplePen.Style);
  6737.     PolarRangeNEdit.AsReal := FPolarRange;
  6738.     PieRowCountComboBox.ItemIndex := FPieRowCount - 1;
  6739.     PrintOrientationComboBox.ItemIndex := Ord(FPrintOrientation);
  6740.     XYFastAtNEdit.AsInteger := FXYFastAt;
  6741.     ZAxisAngleNEdit.AsInteger := ZAngle;
  6742. {$IFDEF DELPHI1}
  6743.     CreatedByEdit.Visible := FALSE;
  6744.     DescriptionEdit.Visible := FALSE;
  6745. {$ELSE}
  6746.     CreatedByEdit.Text := FCreatedBy;
  6747.     DescriptionEdit.Text := FDescription;
  6748. {$ENDIF}
  6749.  
  6750.     if (ShowModal = mrOK) then
  6751.       ApplyPropertiesChange(PlotPropertyEditor);
  6752.   end;
  6753.  
  6754.   PlotPropertyEditor.Free;
  6755.  
  6756.   ZeroScreenStuff;
  6757. end;
  6758.  
  6759. {------------------------------------------------------------------------------
  6760.     Procedure: TCustomPlot.ApplyPropertiesChange
  6761.   Description: This applies changes from the PropertiesDialog.
  6762.        Author: Mat Ballard
  6763.  Date created: 03/28/2001
  6764. Date modified: 03/28/2001 by Mat Ballard
  6765.       Purpose: User interface management
  6766.  Known Issues:
  6767.  ------------------------------------------------------------------------------}
  6768. procedure TCustomPlot.ApplyPropertiesChange(Sender: TObject);
  6769. var
  6770.   OldIgnoreChanges: Boolean;
  6771. begin
  6772.   with TPlotPropertyEditorForm(Sender) do
  6773.   begin
  6774.     OldIgnoreChanges := IgnoreChanges;
  6775.     IgnoreChanges := TRUE;
  6776.     MouseTimer.Interval := ClickAndDragDelayNEdit.AsInteger;
  6777.     Self.Color := BackColorEdit.Color;
  6778.     FBubbleSize := BubbleSizeNEdit.AsInteger;
  6779.     FColumnGap := ColumnGapNEdit.AsInteger;
  6780.     FContourDetail := TContourDetail(ContourDetailComboBox.ItemIndex);
  6781.     FGrid := TGridType(GridComboBox.ItemIndex);
  6782.     FGridStyle := TPenStyle(GridStyleComboBox.ItemIndex);
  6783.     FMultiplePen.Width := PenWidthComboBox.ItemIndex;
  6784.     FMultiplePen.Style := TPenStyle(PenStyleComboBox.ItemIndex);
  6785.     FMultiplicity := MultiplicityComboBox.ItemIndex + 1;
  6786.     FMultiplePen.Color := PenColorEdit.Color;
  6787.     SetMultiJoin(MultiJoinEdit.Text);
  6788.     FPieRowCount := PieRowCountComboBox.ItemIndex + 1;
  6789.     FPolarRange := PolarRangeNEdit.AsReal;
  6790.     FPrintOrientation := TPrinterOrientation(PrintOrientationComboBox.ItemIndex);
  6791.     FXYFastAt := XYFastAtNEdit.AsInteger;
  6792.     ZAngle := ZAxisAngleNEdit.AsInteger;
  6793.     FZLink := LinkZSeriesCheckBox.Checked;
  6794. {$IFNDEF DELPHI1}
  6795.     FCreatedBy := CreatedByEdit.Text;
  6796.     FDescription := DescriptionEdit.Text;
  6797. {$ENDIF}
  6798.     PlotType := TPlotType(PlotTypeComboBox.ItemIndex);
  6799.     IgnoreChanges := OldIgnoreChanges;
  6800.     DoStyleChange(Self);
  6801.   end;
  6802. end;
  6803.  
  6804. {------------------------------------------------------------------------------
  6805.     Procedure: TCustomPlot.EditPointClick
  6806.   Description: Runs the Point Editor of the selected data point
  6807.        Author: Mat Ballard
  6808.  Date created: 12/1/1999
  6809. Date modified: 02/25/2000 by Mat Ballard
  6810.       Purpose:
  6811.  Known Issues:
  6812.  ------------------------------------------------------------------------------}
  6813. procedure TCustomPlot.EditPointClick(
  6814.   Sender: TObject);
  6815. begin
  6816.   if (GetSeriesFromUser) then
  6817.   begin
  6818.     pSeries.EditPoint(ThePointNumber, FHelpFile);
  6819.     //DoStyleChange(Self);
  6820.   end;
  6821.   ZeroScreenStuff;
  6822. end;
  6823.  
  6824. {------------------------------------------------------------------------------
  6825.     Procedure: TCustomPlot.GetNoteFromUser
  6826.   Description: Gets the user to select (if not already done so) a Axis
  6827.        Author: Mat Ballard
  6828.  Date created: 12/1/1999
  6829. Date modified: 02/25/2000 by Mat Ballard
  6830.       Purpose: user interface management
  6831.  Known Issues:
  6832.  ------------------------------------------------------------------------------}
  6833. function TCustomPlot.GetNoteFromUser: Boolean;
  6834. var
  6835.   OptionsDlg: TOptionsDlg;
  6836.   i: Integer;
  6837.   TheNote: Integer;
  6838. begin
  6839. {has the user already selected an object ?}
  6840.   if (ClickedObjectType <> soNote) then
  6841.   begin
  6842.     if (NoteCount = 1) then
  6843.     begin
  6844. {there is only one Note:}
  6845.       ClickedObjectType := soNote;
  6846.       for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  6847.       begin
  6848.         if (TObject(ScreenObjectList.Items[i]) is TNote) then
  6849.         begin
  6850.           pClickedObject := ScreenObjectList.Items[i];
  6851.           break;
  6852.         end;
  6853.       end;
  6854.     end;
  6855.  
  6856.     if (ClickedObjectType <> soNote) then
  6857.   {still no Note selected:}
  6858.     begin
  6859.   {get the user to select an object:}
  6860.       OptionsDlg := TOptionsDlg.Create(nil);
  6861.       OptionsDlg.FormTitle := sWhichNote;
  6862.       OptionsDlg.Question := sWhichNoteDel;
  6863.       for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  6864.       begin
  6865.         if (TObject(ScreenObjectList.Items[i]) is TNote) then
  6866.           OptionsDlg.OptionList.AddObject(
  6867.             TNote(ScreenObjectList.Items[i]).Caption,
  6868.             TNote(ScreenObjectList.Items[i]));
  6869.       end;
  6870.       TheNote := OptionsDlg.Execute - 1;
  6871.       if (TheNote >= 0) then
  6872.       begin
  6873.         ClickedObjectType := soNote;
  6874.         pClickedObject :=
  6875.           OptionsDlg.OptionList.Objects[TheNote];
  6876.           //ScreenObjectList.Items[NoBasicScreenObjects + TheNote];
  6877.       end;
  6878.       OptionsDlg.Free;
  6879.     end; {if object selected}
  6880.   end; {if clicked object is Series}
  6881.   GetNoteFromUser := (ClickedObjectType = soNote);
  6882. end;
  6883.  
  6884. {------------------------------------------------------------------------------
  6885.     Procedure: TCustomPlot.GetSeriesFromUser
  6886.   Description: Gets the user to select (if not already done so) a Axis
  6887.        Author: Mat Ballard
  6888.  Date created: 12/1/1999
  6889. Date modified: 02/25/2000 by Mat Ballard
  6890.       Purpose: user interface management
  6891.  Known Issues:
  6892.  ------------------------------------------------------------------------------}
  6893. function TCustomPlot.GetSeriesFromUser: Boolean;
  6894. var
  6895.   OptionsDlg: TOptionsDlg;
  6896.   i: Integer;
  6897. begin
  6898. {has the user already selected an object ?}
  6899.   if (ClickedObjectType <> soSeries) then
  6900.   begin
  6901.     ThePointNumber := 0;
  6902.     if (FSeriesList.Count = 1) then
  6903.     begin
  6904. {there is only one Series:}
  6905.       ClickedObjectType := soSeries;
  6906.       TheSeries := 0;
  6907.       pSeries := TSeries(FSeriesList.Items[0]);
  6908.     end;
  6909.  
  6910.     if (ClickedObjectType <> soSeries) then
  6911.   {still no Series selected:}
  6912.     begin
  6913.   {get the user to select an object:}
  6914.       OptionsDlg := TOptionsDlg.Create(nil);
  6915.       OptionsDlg.FormTitle := sWhichSeries;
  6916.       OptionsDlg.Question := sWhichSeries2;
  6917.       for i := 0 to FSeriesList.Count-1 do
  6918.       begin
  6919.         OptionsDlg.OptionList.Add(TSeries(FSeriesList.Items[i]).Name);
  6920.       end;
  6921.       TheSeries := OptionsDlg.Execute - 1;
  6922.       if (TheSeries >= 0) then
  6923.       begin
  6924.         ClickedObjectType := soSeries;
  6925.         pSeries := TSeries(FSeriesList.Items[TheSeries]);
  6926.       end;
  6927.       OptionsDlg.Free;
  6928.     end; {if object selected}
  6929.   end; {if clicked object is Series}
  6930.   GetSeriesFromUser := (TheSeries >= 0);
  6931. end;
  6932.  
  6933. {------------------------------------------------------------------------------
  6934.     Procedure: TCustomPlot.GetAxisFromUser
  6935.   Description: Gets the user to select (if not already done so) a Axis
  6936.        Author: Mat Ballard
  6937.  Date created: 06/25/1999
  6938. Date modified: 06/25/2000 by Mat Ballard
  6939.       Purpose: user interface management
  6940.  Known Issues:
  6941.  ------------------------------------------------------------------------------}
  6942. function TCustomPlot.GetAxisFromUser(StartAxis: Word): Boolean;
  6943. var
  6944.   OptionsDlg: TOptionsDlg;
  6945.   i,
  6946.   TheResult: Integer;
  6947. begin
  6948. {has the user already selected an object ?}
  6949. {see GetTheClickedObject}
  6950.   if ((TheAxis >= StartAxis) and (pAxis <> nil)) then
  6951.   begin
  6952.     GetAxisFromUser := TRUE;
  6953.     exit;
  6954.   end;
  6955.  
  6956.   if (StartAxis = FAxisList.Count - 1) then
  6957.   begin
  6958. {there is only one Axis that it could be:}
  6959.     ClickedObjectType := soYAxis;
  6960. {NB: the Y Axes are numbered 1, 2..N:}
  6961.     TheAxis := StartAxis;
  6962.     pAxis := TAxis(FAxisList.Items[TheAxis]);
  6963.     GetAxisFromUser := TRUE;
  6964.     exit;
  6965.   end;
  6966.  
  6967. {still no Axis selected:}
  6968. {get the user to select an object:}
  6969.   OptionsDlg := TOptionsDlg.Create(nil);
  6970.   with OptionsDlg do
  6971.   begin
  6972.     FormTitle := sWhichAxis;
  6973.     Question := sWhichAxis2;
  6974.     for i := StartAxis to FAxisList.Count-1 do
  6975.     begin
  6976.       OptionList.Add(TAxis(FAxisList.Items[i]).Name);
  6977.     end;
  6978.  
  6979.     TheResult := Execute;
  6980.     if (TheResult > 0) then
  6981.     begin
  6982.       TheAxis := StartAxis + TheResult - 1; {Execute = -1, 1,2,3}
  6983.       if (TheAxis = 0) then
  6984.         ClickedObjectType := soXAxis;
  6985.       if (TheAxis > 0) then
  6986.         ClickedObjectType := soYAxis;
  6987.       pAxis := TAxis(FAxisList.Items[TheAxis]);
  6988.     end;
  6989.   end;
  6990.   OptionsDlg.Free;
  6991.  
  6992.   if (TheAxis >= 0) then
  6993.     GetAxisFromUser := TRUE
  6994.    else
  6995.     GetAxisFromUser := FALSE;
  6996. end;
  6997.  
  6998. {------------------------------------------------------------------------------
  6999.     Procedure: TCustomPlot.EditDataClick
  7000.   Description: Runs the Data Editor for the selected Series
  7001.        Author: Mat Ballard
  7002.  Date created: 03/13/2001
  7003. Date modified: 03/13/2001 by Mat Ballard
  7004.       Purpose:
  7005.  Known Issues:
  7006.  ------------------------------------------------------------------------------}
  7007. procedure TCustomPlot.EditDataClick(
  7008.   Sender: TObject);
  7009. begin
  7010.   if (GetSeriesFromUser) then
  7011.   begin
  7012.     pSeries.EditData(FHelpFile);
  7013.   end; {GetSeries}
  7014.   ZeroScreenStuff;
  7015.   Refresh;
  7016. end;
  7017.  
  7018. {------------------------------------------------------------------------------
  7019.     Procedure: TCustomPlot.EditSeriesClick
  7020.   Description: Runs the Series Editor of the selected data Series
  7021.        Author: Mat Ballard
  7022.  Date created: 12/1/1999
  7023. Date modified: 02/25/2000 by Mat Ballard
  7024.       Purpose:
  7025.  Known Issues:
  7026.  ------------------------------------------------------------------------------}
  7027. procedure TCustomPlot.EditSeriesClick(
  7028.   Sender: TObject);
  7029. var
  7030.   i: Integer;
  7031.   SeriesEditor: TSeriesEditorForm;
  7032.   ASP: TSeriesProperty;
  7033.   pSeries: TSeries;
  7034. begin
  7035.   if (GetSeriesFromUser) then
  7036.   begin
  7037.     SeriesEditor := TSeriesEditorForm.Create(nil);
  7038.     SeriesEditor.ThePlot := TObject(Self);
  7039.  
  7040.     with SeriesEditor do
  7041.     begin
  7042.   {Load the Y Axis Combo Box:}
  7043.       for i := 1 to FAxisList.Count-1 do
  7044.       begin
  7045.         YAxisComboBox.Items.Add(TAxis(FAxisList.Items[i]).Title.Caption);
  7046.       end;
  7047.  
  7048.   {Iterate over all series:}
  7049.       for i := 0 to FSeriesList.Count-1 do
  7050.       begin
  7051.         pSeries := TSeries(FSeriesList.Items[i]);
  7052.   {returns 0..MY_COLORS_MAX}
  7053.         ASP.PenColor := pSeries.Pen.Color;
  7054.         ASP.PenWidthIndex := pSeries.Pen.Width;
  7055.         ASP.PenStyleIndex := Ord(pSeries.Pen.Style);
  7056.         ASP.BrushColor := pSeries.Brush.Color;
  7057.         ASP.BrushStyleIndex := Ord(pSeries.Brush.Style);
  7058.         ASP.SymbolIndex := Ord(pSeries.Symbol);
  7059.         ASP.SymbolSize := pSeries.SymbolSize;
  7060.         ASP.YAxisIndex := pSeries.YAxisIndex;
  7061.         ASP.DeltaX := pSeries.DeltaX;
  7062.         ASP.DeltaY := pSeries.DeltaY;
  7063.         ASP.XDataIndependent := not pSeries.ExternalXSeries;
  7064.         ASP.ExternalXSeries := pSeries.ExternalXSeries;
  7065.         ASP.Visible := pSeries.Visible;
  7066.         AddSeries(pSeries.Name, ASP);
  7067.       end;
  7068.       NoComboBox.ItemIndex := TheSeries;
  7069.       SelectSeries(TheSeries);
  7070.  
  7071.       SeriesEditor.HelpFile := FHelpFile;
  7072.  
  7073.       if (ShowModal = mrOK) then
  7074.         ApplySeriesChange(SeriesEditor);
  7075.     end; {with SeriesEditor}
  7076.     SeriesEditor.Free;
  7077.   end;
  7078.   ZeroScreenStuff;
  7079. end;
  7080.  
  7081. {------------------------------------------------------------------------------
  7082.     Procedure: TCustomPlot.ApplySeriesChange
  7083.   Description: This applies changes from the SeriesEditor Dialog.
  7084.        Author: Mat Ballard
  7085.  Date created: 03/28/2001
  7086. Date modified: 03/28/2001 by Mat Ballard
  7087.       Purpose: User interface management
  7088.  Known Issues:
  7089.  ------------------------------------------------------------------------------}
  7090. procedure TCustomPlot.ApplySeriesChange(Sender: TObject);
  7091. var
  7092.   i: Integer;
  7093.   pSeries: TSeries;
  7094.   pASP: ^TSeriesProperty;
  7095. begin
  7096.   for i := 0 to FSeriesList.Count-1 do
  7097.   begin
  7098.     pASP := TSeriesEditorForm(Sender).SeriesPropertyList.Items[i];
  7099.     pSeries := TSeries(FSeriesList.Items[i]);
  7100.     pSeries.Pen.Color := pASP^.PenColor;
  7101.     pSeries.Pen.Width := pASP^.PenWidthIndex;
  7102.     pSeries.Pen.Style := TPenStyle(pASP^.PenStyleIndex);
  7103.     pSeries.Brush.Color := pASP^.BrushColor;
  7104.     pSeries.Brush.Style := TBrushStyle(pASP.BrushStyleIndex);
  7105.     pSeries.Symbol := TSymbol(pASP^.SymbolIndex);
  7106.     pSeries.SymbolSize := pASP^.SymbolSize;
  7107.     pSeries.YAxisIndex := pASP^.YAxisIndex;
  7108.     pSeries.DeltaX := pASP^.DeltaX;
  7109.     pSeries.DeltaY := pASP^.DeltaY;
  7110.     pSeries.Visible := pASP^.Visible;
  7111.     pSeries.Name := TSeriesEditorForm(Sender).SeriesNames.Strings[i];
  7112.     if ((pASP^.XDataIndependent) and (pSeries.ExternalXSeries)) then
  7113.     begin
  7114. {this series did depend on X Data in another series,
  7115. but user wants to make it independent:}
  7116.       pSeries.MakeXDataIndependent;
  7117.     end;
  7118.   end; {for}
  7119.   DoStyleChange(Self);
  7120. end;
  7121.  
  7122. {------------------------------------------------------------------------------
  7123.     Procedure: TCustomPlot.ResetDisplacementClick
  7124.   Description: Puts the selected Axis back where it came from
  7125.        Author: Mat Ballard
  7126.  Date created: 12/1/1999
  7127. Date modified: 02/25/2000 by Mat Ballard
  7128.       Purpose: sets the DeltaX and DeltaY properties of the selected Axis to ZeroScreenStuff
  7129.  Known Issues:
  7130.  ------------------------------------------------------------------------------}
  7131. procedure TCustomPlot.ResetDisplacementClick(
  7132.   Sender: TObject);
  7133. begin
  7134.   if (GetSeriesFromUser) then
  7135.   begin
  7136.     pSeries.DeltaX := 0;
  7137.     pSeries.DeltaY := 0;
  7138.     DoStyleChange(Self);
  7139.   end;
  7140.   ZeroScreenStuff;
  7141. end;
  7142.  
  7143. {File manipulation ------------------------------------------------------------}
  7144. {------------------------------------------------------------------------------
  7145.     Procedure: TCustomPlot.NewClick
  7146.   Description: Creates a new, blank Graph
  7147.        Author: Mat Ballard
  7148.  Date created: 02/25/2000
  7149. Date modified: 02/25/2000 by Mat Ballard
  7150.       Purpose: data management
  7151.  Known Issues:
  7152.  ------------------------------------------------------------------------------}
  7153. procedure TCustomPlot.NewClick(
  7154.   Sender: TObject);
  7155. begin
  7156.   Self.Clear(TRUE);
  7157. end;
  7158.  
  7159. {------------------------------------------------------------------------------
  7160.     Procedure: TPlot.Notification
  7161.   Description: needed for D1
  7162.        Author: Mat Ballard
  7163.  Date created: 09/07/2000
  7164. Date modified: 09/07/2000 by Mat Ballard
  7165.       Purpose:
  7166.  Known Issues:
  7167.  ------------------------------------------------------------------------------}
  7168. procedure TCustomPlot.Notification(AComponent: TComponent;
  7169.   Operation: TOperation);
  7170. begin
  7171.   inherited Notification(AComponent, Operation);
  7172.   {if (Operation = opRemove) and (AComponent = Plot) then
  7173.   begin
  7174.     Plot := nil;
  7175.   end;}
  7176. end;
  7177.  
  7178. {------------------------------------------------------------------------------
  7179.     Procedure: TCustomPlot.OpenClick
  7180.   Description: Opens a file on disk
  7181.        Author: Mat Ballard
  7182.  Date created: 02/25/2000
  7183. Date modified: 02/25/2000 by Mat Ballard
  7184.       Purpose: Runs the File Open common dialog then the LoadFromFile method
  7185.  Known Issues:
  7186.  ------------------------------------------------------------------------------}
  7187. procedure TCustomPlot.OpenClick(
  7188.   Sender: TObject);
  7189. var
  7190.   OpenDialog: TOpenDialog;
  7191. begin
  7192. {We have to display a File Open Dialog:}
  7193.   OpenDialog := TOpenDialog.Create(Self);
  7194.   OpenDialog.Title := sOpen;
  7195.   OpenDialog.Filter := FileTypes;
  7196.   OpenDialog.Options := [ofOverwritePrompt];
  7197.   if (Length(FFileName) = 0) then
  7198.   begin
  7199.     FileName := '*.' + FDefaultExtension;
  7200.   end;
  7201.  
  7202.   OpenFilterIndex := GetFilterIndex(GetFileExtension);
  7203.   OpenDialog.FilterIndex := OpenFilterIndex;
  7204.  
  7205.   OpenDialog.FileName := '*.' + GetFileExtension;
  7206.  
  7207.   if (Length(OpenDriveDir) > 0) then
  7208.     OpenDialog.InitialDir := ExtractFileName(OpenDriveDir)
  7209.    else
  7210.     OpenDialog.InitialDir := GetFileDriveDir;
  7211.  
  7212.   if (OpenDialog.Execute) then
  7213.   begin
  7214.     OpenFile(OpenDialog.FileName);
  7215.     OpenFilterIndex := OpenDialog.FilterIndex;
  7216.   end;
  7217.   OpenDialog.Free;
  7218.  
  7219.   //ZoomOutClick(Self);
  7220. end;
  7221.  
  7222. {------------------------------------------------------------------------------
  7223.     Procedure: TCustomPlot.OpenFile
  7224.   Description: Opens a file on disk
  7225.        Author: Mat Ballard
  7226.  Date created: 08/12/2000
  7227. Date modified: 08/12/2000 by Mat Ballard
  7228.       Purpose: Called from TPlotMenu.HandleFileClick
  7229.  Known Issues:
  7230.  ------------------------------------------------------------------------------}
  7231. procedure TCustomPlot.OpenFile(
  7232.   TheFile: String);
  7233. begin
  7234.   if (FileExists(TheFile)) then
  7235.   begin
  7236. {Delete any existing Series:}
  7237.     Clear(FALSE);
  7238.     FileName := TheFile;
  7239.     OpenDriveDir := ExtractFilePath(FFileName);
  7240. {Finally, Open it:}
  7241.     LoadFromFile(FFileName);
  7242.  
  7243.     DoFileOpen(FFileName);
  7244.   end;
  7245.  
  7246.   ZoomOutClick(Self);
  7247. end;
  7248.  
  7249. {------------------------------------------------------------------------------
  7250.     Procedure: TCustomPlot.DoFileOpen
  7251.   Description: Fires the OnFileOpen event
  7252.        Author: Mat Ballard
  7253.  Date created: 09/07/2000
  7254. Date modified: 09/07/2000 by Mat Ballard
  7255.       Purpose:
  7256.  Known Issues:
  7257.  ------------------------------------------------------------------------------}
  7258. procedure TCustomPlot.DoFileOpen(AFileName: String);
  7259. begin
  7260.   if Assigned(FOnFileOpen) then
  7261.     OnFileOpen(Self, AFileName);
  7262. end;
  7263.  
  7264.  
  7265. {------------------------------------------------------------------------------
  7266.     Procedure: TCustomPlot.ClearOverlaysClick
  7267.   Description: Gets rid of the overlaid data
  7268.        Author: Mat Ballard
  7269.  Date created: 02/25/2000
  7270. Date modified: 02/25/2000 by Mat Ballard
  7271.       Purpose: Runs the FSeriesList.Delete method for each overlaid Axis
  7272.  Known Issues:
  7273.  ------------------------------------------------------------------------------}
  7274. procedure TCustomPlot.ClearOverlaysClick(
  7275.   Sender: TObject);
  7276. var
  7277.   i: Integer;
  7278. begin
  7279.   if (FirstOverlay < 0) then raise
  7280.     EComponentError.Create(sClearOverlays);
  7281.  
  7282.   for i := FSeriesList.Count-1 downto FirstOverlay do
  7283.   begin
  7284.     TSeries(FSeriesList.Items[i]).Free;
  7285.     FSeriesList.Delete(i);
  7286.   end;
  7287.   FirstOverlay := -1;
  7288.   DoStyleChange(Self);
  7289. end;
  7290.  
  7291. {------------------------------------------------------------------------------
  7292.     Procedure: TCustomPlot.OverlayDataClick
  7293.   Description: Overlays data
  7294.        Author: Mat Ballard
  7295.  Date created: 02/25/2000
  7296. Date modified: 02/25/2000 by Mat Ballard
  7297.       Purpose: Runs the Open common dialog, then LoadFromFile the selected files
  7298.  Known Issues:
  7299.  ------------------------------------------------------------------------------}
  7300. procedure TCustomPlot.OverlayClick(
  7301.   Sender: TObject);
  7302. var
  7303.   i: Integer;
  7304.   OverlayDialog: TOpenDialog;
  7305. begin
  7306. {We have to display a File Overlay Dialog:}
  7307.   OverlayDialog := TOpenDialog.Create(Self);
  7308.   OverlayDialog.Title := sOverlay1;
  7309.   OverlayDialog.Filter := FileTypes;
  7310.   OverlayDialog.Options :=
  7311.     [ofFileMustExist, ofPathMustExist, ofAllowMultiSelect];
  7312.  
  7313.   OverlayDialog.FileName := '*.' + FDefaultExtension;
  7314.  
  7315.   OverlayDialog.FilterIndex := OpenFilterIndex;
  7316.  
  7317.   if (Length(OverlayDriveDir) > 0) then
  7318.     OverlayDialog.InitialDir := ExtractFileName(OpenDriveDir)
  7319.    else
  7320.     OverlayDialog.InitialDir := GetFileDriveDir;
  7321.  
  7322.   if (OverlayDialog.Execute) then
  7323.   begin
  7324.     FirstOverlay := FSeriesList.Count;
  7325.     for i := 0 to OverlayDialog.Files.Count - 1 do
  7326.     begin
  7327.       OverlayDriveDir := ExtractFileName(OverlayDialog.Files.Strings[i]);
  7328. {Finally, Overlay it:}
  7329.       Self.LoadFromFile(OverlayDialog.Files.Strings[i]);
  7330.     end;
  7331.   end;
  7332.   OverlayDialog.Free;
  7333.  
  7334.   ZoomOutClick(Self);
  7335. end;
  7336.  
  7337. {------------------------------------------------------------------------------
  7338.     Procedure: TCustomPlot.SaveImageClick
  7339.   Description: saves the current plot as an image
  7340.        Author: Mat Ballard
  7341.  Date created: 04/25/2000
  7342. Date modified: 04/25/2000 by Mat Ballard
  7343.       Purpose: responds to "Save Image" menu selection
  7344.  Known Issues:
  7345.  ------------------------------------------------------------------------------}
  7346. procedure TCustomPlot.SaveImageClick(Sender: TObject);
  7347. var
  7348.   SaveImageDialog: TSaveDialog;
  7349.   Extension, ImageName: String;
  7350. begin
  7351. {We have to display a File Save Dialog:}
  7352.   SaveImageDialog := TSaveDialog.Create(Self);
  7353.   SaveImageDialog.Title := sSaveImage1;
  7354.   SaveImageDialog.Filter := PICTURE_TYPES;
  7355.   SaveImageDialog.Options := [ofOverwritePrompt];
  7356.  
  7357.   if (Length(ImageDriveDir) = 0) then
  7358.     if (Length(FFileName) > 0) then
  7359.       ImageDriveDir := GetFileDriveDir;
  7360.  
  7361.   SaveImageDialog.FilterIndex := ImageFilterIndex;
  7362. {which starts off at zero, then  may change}
  7363.  
  7364.   if (Length(FFileName) > 0) then
  7365.   begin
  7366.     SaveImageDialog.FileName :=
  7367.       GetFileRoot + '.' + ImageExtensions[ImageFilterIndex-1];
  7368.   end
  7369.   else
  7370.   begin
  7371.     SaveImageDialog.FileName :=
  7372.       '*.' + ImageExtensions[ImageFilterIndex-1];
  7373.   end;
  7374.  
  7375.   SaveImageDialog.InitialDir := ImageDriveDir;
  7376.  
  7377.   if (SaveImageDialog.Execute) then
  7378.   begin
  7379.     ImageName := SaveImageDialog.FileName;
  7380.     ImageDriveDir := ExtractFilePath(ImageName);
  7381.  
  7382.     Extension := LowerCase(ExtractFileExt(ImageName));
  7383.     if (Length(Extension) = 0) then
  7384.     begin
  7385.       ImageName := ImageName + '.' +
  7386.         ImageExtensions[SaveImageDialog.FilterIndex-1];
  7387.     end;
  7388.  
  7389. {Finally, save it:}
  7390. {We base this on the extension, rather than FilterIndex:}
  7391.     if (Extension = '.bmp') then
  7392.     begin
  7393.       ImageFilterIndex := 3;
  7394.       SaveAsBitMap(ImageName);
  7395.     end;
  7396. {$IFDEF MSWINDOWS}
  7397.     if (Extension = '.wmf') then
  7398.     begin
  7399.       ImageFilterIndex := 1;
  7400.       SaveAsDrawing(ImageName);
  7401.     end
  7402.     else if (Extension = '.emf') then
  7403.     begin
  7404.       ImageFilterIndex := 2;
  7405.       SaveAsDrawing(ImageName);
  7406.     end;
  7407. {$ENDIF}
  7408. {$IFDEF GIF}
  7409.     if (Extension = '.gif') then
  7410.     begin
  7411.       ImageFilterIndex := 4;
  7412.       SaveAsGIF(ImageName);
  7413.     end;
  7414. {$ENDIF}
  7415. {$IFDEF PNG}
  7416.     if (Extension = '.png') then
  7417.     begin
  7418.       ImageFilterIndex := 5;
  7419.       SaveAsPNG(ImageName);
  7420.     end;
  7421. {$ENDIF}
  7422.   end;
  7423.   SaveImageDialog.Free;
  7424. end;
  7425.  
  7426. {------------------------------------------------------------------------------
  7427.     Procedure: TCustomPlot.SaveClick
  7428.   Description: Saves the graph
  7429.        Author: Mat Ballard
  7430.  Date created: 02/25/2000
  7431. Date modified: 02/25/2000 by Mat Ballard
  7432.       Purpose: Runs SaveToFile or SaveAsClick
  7433.  Known Issues:
  7434.  ------------------------------------------------------------------------------}
  7435. procedure TCustomPlot.SaveClick(Sender: TObject);
  7436. begin
  7437.   if (Length(FFileName) > 0) then
  7438.     SaveToFile(FFileName)
  7439.    else
  7440.     SaveAsClick(Sender);
  7441. end;
  7442.  
  7443. {------------------------------------------------------------------------------
  7444.     Procedure: TCustomPlot.SaveAsClick
  7445.   Description: Saves the data to disk
  7446.        Author: Mat Ballard
  7447.  Date created: 02/25/2000
  7448. Date modified: 02/25/2000 by Mat Ballard
  7449.       Purpose: Runs the Save common dialog box then SaveToFile
  7450.  Known Issues:
  7451.  ------------------------------------------------------------------------------}
  7452. procedure TCustomPlot.SaveAsClick(Sender: TObject);
  7453. var
  7454.   Ext: String;
  7455.   SaveDialog: TSaveDialog;
  7456. begin
  7457. {We have to display a File Save Dialog:}
  7458.   SaveDialog := TSaveDialog.Create(Self);
  7459.   SaveDialog.Title := sSaveAs1;
  7460.   SaveDialog.Filter := FileTypes;
  7461.   SaveDialog.Options := [ofOverwritePrompt];
  7462.   if (Length(FFileName) = 0) then
  7463.   begin
  7464.     FileName := '*.' + FDefaultExtension;
  7465.   end;
  7466.  
  7467.   SaveFilterIndex := GetFilterIndex(GetFileExtension);
  7468.   SaveDialog.FilterIndex := SaveFilterIndex;
  7469.  
  7470.   SaveDialog.InitialDir := GetFileDriveDir;
  7471.   SaveDialog.FileName := ExtractFileName(FFileName);
  7472.  
  7473.   if (SaveDialog.Execute) then
  7474.   begin
  7475.     FileName := SaveDialog.FileName;
  7476.     Ext := GetFileExtension;
  7477.     if (Length(Ext) = 0) then
  7478.     begin
  7479.       Ext := FileExtensions[SaveDialog.FilterIndex];
  7480.       FileName := FileName + '.' + Ext;
  7481.     end;
  7482.  
  7483. {Double-whammy problem: save with 'plot'extension, but different filter,
  7484.  should save in that (text) format.
  7485.  Save with other extension, but FilterIndex=0 (plot type), then extension
  7486.  should override, so also save in text.}
  7487.  
  7488.     if ((Ext = FileExtensions[0]) and (SaveDialog.FilterIndex = 1)) then
  7489.     begin {.plot}
  7490.       SaveFilterIndex := 1;
  7491.       FAsText := FALSE or (soAsText in FSaveOptions);
  7492.     end {.plot}
  7493.     else if ((Ext = FileExtensions[0]) and (SaveDialog.FilterIndex > 1)) then
  7494.     begin {'plot' extension, text type}
  7495.       SaveFilterIndex := 1;
  7496.       FAsText := TRUE;
  7497.     end {'plot' extension, text type}
  7498.     else if (Ext = FileExtensions[1]) then
  7499.     begin {.csv}
  7500.       SaveFilterIndex := 2;
  7501.       FAsText := TRUE;
  7502.     end {.csv}
  7503.     else if (Ext = FileExtensions[2]) then
  7504.     begin
  7505.       SaveFilterIndex := 3;
  7506.       FAsText := TRUE;
  7507.     end {.txt}
  7508.     else
  7509.     begin
  7510.       SaveFilterIndex := 4;
  7511.       FAsText := TRUE;
  7512.     end; {.*}
  7513.  
  7514. {Finally, save it:}
  7515.     Self.SaveToFile(FFileName);
  7516.     SaveFilterIndex := SaveDialog.FilterIndex;
  7517.   end;
  7518.   SaveDialog.Free;
  7519. end;
  7520.  
  7521. {Saving data to disk --------------------------------------------------------}
  7522. {------------------------------------------------------------------------------
  7523.     Procedure: TCustomPlot.LoadFromFile
  7524.   Description: Opens data on disk
  7525.        Author: Mat Ballard
  7526.  Date created: 02/25/2000
  7527. Date modified: 02/25/2000 by Mat Ballard
  7528.       Purpose: Opens the data and feeds it into LoadFromStream
  7529.  Known Issues: Can be called by either OpenClick or OverlayClick
  7530.  ------------------------------------------------------------------------------}
  7531. procedure TCustomPlot.LoadFromFile(
  7532.   AFileName: String);
  7533. var
  7534.  TheStream: TMemoryStream;
  7535. begin
  7536.  TheStream := TMemoryStream.Create;
  7537.  try
  7538.    TheStream.LoadFromFile(AFileName);
  7539.    Self.LoadFromStream(TheStream);
  7540.  finally
  7541.    TheStream.Free;
  7542.  end;
  7543. end;
  7544.  
  7545. {------------------------------------------------------------------------------
  7546.     Procedure: TCustomPlot.LoadFromStream
  7547.   Description: Opens data on disk
  7548.        Author: Mat Ballard
  7549.  Date created: 02/25/2000
  7550. Date modified: 02/25/2000 by Mat Ballard
  7551.       Purpose: Opens data, parses it, fires the OnHeader event, and runs ConvertTextData,
  7552.                or decides to run it through ParseData instead
  7553.  Known Issues: Can be called by either OpenClick or OverlayClick
  7554.  ------------------------------------------------------------------------------}
  7555. procedure TCustomPlot.LoadFromStream(
  7556.   AStream: TMemoryStream);
  7557. var
  7558.   TheResult: Boolean;
  7559.   TheStrings: TStringList;
  7560.   OldIgnoreChanges: Boolean;
  7561.  
  7562.   function IsPlotFile: Boolean;
  7563.   var
  7564.     FileVersion: Integer;
  7565.     TheLine: String;
  7566.   begin
  7567.     IsPlotFile := FALSE;
  7568. {Line the first:}
  7569.     TheLine := ReadLine(AStream);
  7570.     if (Pos('TPlot', TheLine) = 0) then exit;
  7571.  
  7572. {Line the second:}
  7573.     TheLine := ReadLine(AStream);
  7574.     if (Pos('FileFormat', TheLine) = 0) then exit;
  7575.     GetWord(TheLine, '=');
  7576.     FileVersion := StrToInt(TheLine);
  7577.     if (FileVersion > MAX_FILE_VERSION) then exit;
  7578.  
  7579.     FTitle.Caption := ReadLine(AStream);
  7580.  
  7581. {Now comes the developer-defined header:}
  7582.     DoHeader(AStream);
  7583.  
  7584.     TheLine := ReadLine(AStream);
  7585.     if (TheLine <> SUBHEADER) then
  7586.     begin
  7587. {either a stuffed file, or the developer has done a naughty
  7588.  and overrun his own header; we therefore try to find it from the beginning,
  7589.  then reset the srteam position:}
  7590.       AStream.Position := 0;
  7591.       if (not (FindStringInStream(SUBHEADER, AStream))) then exit;
  7592.       TheLine := ReadLine(AStream);
  7593.     end;
  7594.     IsPlotFile := TRUE;
  7595.   end;
  7596.  
  7597. begin
  7598.   OldIgnoreChanges := IgnoreChanges;
  7599.   IgnoreChanges := TRUE;
  7600.  
  7601.   if (IsPlotFile) then
  7602.   begin
  7603.     TheResult := FSeriesList.LoadFromStream(AStream, FAsText);
  7604.   end
  7605.   else
  7606.   begin
  7607. {maybe it's just a text file:}
  7608.     AStream.Seek(0, soFromBeginning);
  7609.     TheStrings := TStringList.Create;
  7610.     try
  7611.       TheStrings.LoadFromStream(AStream);
  7612.       TheResult := FSeriesList.ParseData(TheStrings, FHelpFile);
  7613.       {FAsText := TRUE;}
  7614.     finally
  7615.       if (TheStrings <> nil) then
  7616.         TheStrings.Free;
  7617.     end;
  7618.   end; {IsPlotFile}
  7619.  
  7620.   if (TheResult) then OpenProperties('');
  7621.  
  7622.   IgnoreChanges := OldIgnoreChanges;
  7623.   ZoomOutClick(Self);
  7624. end;
  7625.  
  7626. {------------------------------------------------------------------------------
  7627.     Procedure: TCustomPlot.DoHeader
  7628.   Description: Informs the user of a user-defined file header
  7629.        Author: Mat Ballard
  7630.  Date created: 09/07/2000
  7631. Date modified: 09/07/2000 by Mat Ballard
  7632.       Purpose: Fires the OnHeader event
  7633.  Known Issues:
  7634.  ------------------------------------------------------------------------------}
  7635. procedure TCustomPlot.DoHeader(TheStream: TMemoryStream);
  7636. begin
  7637.   if assigned(FOnHeader) then
  7638.     OnHeader(Self, TheStream);
  7639. end;
  7640.  
  7641. {------------------------------------------------------------------------------
  7642.     Procedure: TCustomPlot.SaveToFile
  7643.   Description: Saves the data as text
  7644.        Author: Mat Ballard
  7645.  Date created: 02/25/2000
  7646. Date modified: 03/07/2001 by Mat Ballard
  7647.       Purpose: Fires the OnHeaderRequest event, then the GetData of SeriesList
  7648.  Known Issues:
  7649.       Comment: Note that we now use a TStream.
  7650.  ------------------------------------------------------------------------------}
  7651. procedure TCustomPlot.SaveToFile(
  7652.   AFileName: String);
  7653. var
  7654.   TheStream: TMemoryStream;
  7655. begin
  7656.   TheStream := TMemoryStream.Create;
  7657. {create the data in binary or text format:}
  7658.   Self.SaveToStream(TheStream);
  7659.  
  7660. {determine the file name:}
  7661.   if (Length(AFileName) > 0) then
  7662.     SetFileName(AFileName);
  7663.  
  7664. {save it:}
  7665.   TheStream.SaveToFile(FFileName);
  7666.  
  7667.   TheStream.Free;
  7668.  
  7669.   if (soProperties in FSaveOptions) then
  7670.     SaveTheProperties('');
  7671. end;
  7672.  
  7673. {------------------------------------------------------------------------------
  7674.     Procedure: TCustomPlot.SaveToStream
  7675.   Description: Saves the data as text
  7676.        Author: Mat Ballard
  7677.  Date created: 02/25/2000
  7678. Date modified: 03/07/2001 by Mat Ballard
  7679.       Purpose: Fires the OnHeaderRequest event, then the GetData of SeriesList
  7680.  Known Issues:
  7681.       Comment: Note that we now use a TStream.
  7682.  ------------------------------------------------------------------------------}
  7683. procedure TCustomPlot.SaveToStream(var TheStream: TMemoryStream);
  7684. var
  7685.   pLine: array [0..1023] of char;
  7686. begin
  7687.   if (TheStream = nil) then
  7688.     TheStream := TMemoryStream.Create;
  7689.  
  7690. {D1 does not like Pointer(TheLine)^:
  7691.   TheLine := 'TPlot=' + IntToStr(TPLOT_VERSION) + CRLF;
  7692.   TheStream.Write(Pointer(TheLine)^, Length(TheLine));
  7693. so:}
  7694.   StrPCopy(pLine, 'TPlot=' + IntToStr(TPLOT_VERSION) + CRLF);
  7695.   TheStream.Write(pLine, StrLen(pLine));
  7696.   StrPCopy(pLine, 'FileFormat=' + IntToStr(FILE_FORMAT_VERSION) + CRLF);
  7697.   TheStream.Write(pLine, StrLen(pLine));
  7698.  
  7699.   StrPCopy(pLine, FTitle.Caption + CRLF);
  7700.   TheStream.Write(pLine, StrLen(pLine));
  7701.  
  7702.   DoHeaderRequest(TheStream);
  7703.  
  7704.   StrPCopy(pLine, SUBHEADER + CRLF);
  7705.   TheStream.Write(pLine, StrLen(pLine));
  7706.  
  7707. {create the data in binary or text format:}
  7708.   FSeriesList.GetStream(FAsText, ',', TheStream);
  7709. end;
  7710.  
  7711. {------------------------------------------------------------------------------
  7712.     Procedure: TCustomPlot.DoHeaderRequest
  7713.   Description: Asks the user for a header
  7714.        Author: Mat Ballard
  7715.  Date created: 09/07/2000
  7716. Date modified: 09/07/2000 by Mat Ballard
  7717.       Purpose: Fires the OnHeaderRequest event
  7718.  Known Issues:
  7719.  ------------------------------------------------------------------------------}
  7720. procedure TCustomPlot.DoHeaderRequest(TheStream: TMemoryStream);
  7721. begin
  7722.   if assigned(FOnHeaderRequest) then
  7723.     OnHeaderRequest(Self, TheStream);
  7724. end;
  7725.  
  7726. {------------------------------------------------------------------------------
  7727.     Procedure: TCustomPlot.OpenProperties
  7728.   Description: Opens the properties of this instance of TPlot
  7729.        Author: Mat Ballard
  7730.  Date created: 08/03/2000
  7731. Date modified: 08/03/2000 by Mat Ballard
  7732.       Purpose: Saves the appearance of the Plot
  7733.  Known Issues:
  7734.       Comment: Note that if AFileName is blank, we use a name generated from
  7735.                the FileName property (in SetFileName).
  7736.  ------------------------------------------------------------------------------}
  7737. procedure TCustomPlot.OpenProperties(AFileName: String);
  7738. var
  7739.   FileStream: TFileStream;
  7740.   OldIgnoreChanges: Boolean;
  7741. begin
  7742.   if (Length(AFileName) > 0) then
  7743.     PropsFileName := AFileName;
  7744.  
  7745.   if (FileExists(PropsFileName)) then
  7746.   begin
  7747.     OldIgnoreChanges := IgnoreChanges;
  7748.     IgnoreChanges := TRUE;
  7749.     FileStream := TFileStream.Create(PropsFileName, fmOpenRead + fmShareDenyWrite);
  7750.     try
  7751. {This is what causes multiple screen redraws. But why ?}
  7752.       FileStream.ReadComponent(Self);
  7753.       {The following dont work; TAxis descends from TPersistent !
  7754.       for i := 2 to FAxisList.Count-1 do
  7755.       begin
  7756.         TAxis(FAxisList[i]).ReadComponent(TAxis(FAxisList[i]));
  7757.       end;}
  7758.     finally
  7759.       IgnoreChanges := OldIgnoreChanges;
  7760.       FileStream.Free;
  7761.     end;
  7762.   end;
  7763. end;
  7764.  
  7765. {------------------------------------------------------------------------------
  7766.     Procedure: TCustomPlot.SaveTheProperties
  7767.   Description: Saves the properties of this instance of TPlot
  7768.        Author: Mat Ballard
  7769.  Date created: 08/03/2000
  7770. Date modified: 08/03/2000 by Mat Ballard
  7771.       Purpose: Saves the appearance of the Plot
  7772.  Known Issues:
  7773.       Comment: Note that if AFileName is blank, we use a name generated from
  7774.                the FileName property (in SetFileName).
  7775.  ------------------------------------------------------------------------------}
  7776. procedure TCustomPlot.SaveTheProperties(AFileName: String);
  7777. var
  7778.   FileStream: TFileStream;
  7779. begin
  7780.   if (Length(AFileName) > 0) then
  7781.     PropsFileName := AFileName;
  7782.  
  7783.   FileStream := TFileStream.Create(PropsFileName, fmCreate or fmShareExclusive);
  7784.   FileStream.WriteComponent(Self);
  7785.   {The following dont work; TAxis descends from TPersistent !
  7786.   for i := 2 to FAxisList.Count-1 do
  7787.   begin
  7788.     TAxis(FAxisList[i]).WriteComponent(TAxis(FAxisList[i]));
  7789.   end;}
  7790.   FileStream.Free;
  7791. end;
  7792.  
  7793. {------------------------------------------------------------------------------
  7794.     Procedure: TCustomPlot.AppendToFile
  7795.   Description: Appends the data to FileName
  7796.        Author: Mat Ballard
  7797.  Date created: 02/25/2000
  7798. Date modified: 02/25/2000 by Mat Ballard
  7799.       Purpose: Runs the GetData method of SeriesList, then the Append method of the new TFileList
  7800.  Known Issues: Needs work on GetData and testing
  7801.  ------------------------------------------------------------------------------}
  7802. procedure TCustomPlot.AppendToFile;
  7803. var
  7804.   TheStream: TMemoryStreamEx;
  7805. begin
  7806.   if (FileExists(FFileName)) then
  7807.   begin
  7808. {create the FileList, an extension of TStringList:}
  7809.     TheStream := TMemoryStreamEx.Create;
  7810.  
  7811. {create the data in text format:}
  7812.     FSeriesList.AppendStream((soAsText in FSaveOptions), ',', TheStream);
  7813. {save it:}
  7814.     TheStream.AppendToFile(FFileName);
  7815.  
  7816.     TheStream.Free;
  7817.   end
  7818.   else
  7819.   begin
  7820.     EComponentError.Create('TCustomPlot.AppendToFile: ' + FFileName + sDoesNoTExist);
  7821.   end;
  7822. end;
  7823.  
  7824. {Copying data to the clipboard ----------------------------------------------}
  7825. {------------------------------------------------------------------------------
  7826.     Procedure: TCustomPlot.CopyHTML
  7827.   Description: Copies data as HTML to Clipboard
  7828.        Author: Mat Ballard
  7829.  Date created: 02/25/2000
  7830. Date modified: 02/25/2000 by Mat Ballard
  7831.       Purpose: Creates a Header, fires the OnHTMLHeaderRequest event, then runs
  7832.                the DataAsHTMLTable method of SeriesList
  7833.  Known Issues:
  7834.  ------------------------------------------------------------------------------}
  7835. procedure TCustomPlot.CopyHTML(Format: Word);
  7836. var
  7837.   i: Integer;
  7838.   TheData,
  7839.   TheHeader: TStringList;
  7840. {$IFDEF DELPHI1}
  7841.   pLine: array [0..1023] of char;
  7842. {$ENDIF}
  7843. {$IFDEF MSWINDOWS}
  7844.   Size,
  7845.   LineLength: LongInt;
  7846.   pText,
  7847.   TextPtr: PChar;
  7848.   TextHandle: THandle;
  7849. {$ENDIF}
  7850. begin
  7851.   TheHeader := TStringList.Create;
  7852.   TheHeader.Add('<html>');
  7853.   TheHeader.Add('<head>');
  7854.   TheHeader.Add('<title>' + FTitle.Caption + '</title>');
  7855.   TheHeader.Add('</head>');
  7856.   TheHeader.Add('<body bgcolor="white">');
  7857.   TheHeader.Add('<h1>' + FTitle.Caption + '</h1>');
  7858.   TheHeader.Add('<p>');
  7859.  
  7860.   DoHTMLHeaderRequest(TheHeader);
  7861.  
  7862.   TheData := TStringList.Create;
  7863.  
  7864. {create the data in text format:}
  7865.   FSeriesList.DataAsHTMLTable(TheData);
  7866. {insert the header:}
  7867.   for i := 0 to TheHeader.Count-1 do
  7868.     TheData.Insert(0, TheHeader[i]);
  7869.  
  7870. {$IFDEF MSWINDOWS}
  7871. {Calculate the size:}
  7872.   Size := 8;
  7873.   for i := 0 to TheData.Count-1 do
  7874.     Inc(Size, Length(TheData[i])+2);
  7875. {save it:}
  7876.   TextHandle := GlobalAlloc(GMEM_MOVEABLE, Size);
  7877.   TextPtr := GlobalLock(TextHandle);
  7878.  
  7879.   pText := TextPtr;
  7880.   for i := 0 to TheData.Count - 1 do
  7881.   begin
  7882.     LineLength := Length(TheData[i]);
  7883.     if LineLength <> 0 then
  7884.     begin
  7885. {$IFDEF DELPHI1}
  7886.       StrPCopy(pLine, TheData[i]);
  7887.       System.Move(pLine, pText^, LineLength);
  7888. {$ELSE}
  7889. {for some unknown reason, this Move works !}
  7890.       System.Move(Pointer(TheData[i])^, pText^, LineLength);
  7891. {$ENDIF}
  7892.       Inc(pText, LineLength);
  7893.     end;
  7894.     pText^ := #13;
  7895.     Inc(pText);
  7896.     pText^ := #10;
  7897.     Inc(pText);
  7898.   end;       
  7899. {we need to use SetAsHandle because Format may be CF_HTML:}
  7900.   ClipBoard.SetAsHandle(Format, TextHandle);
  7901.   GlobalUnlock(TextHandle);
  7902. {$ENDIF}
  7903. {$IFDEF LINUX}
  7904.   Clipboard.AsText := TheData.Text;
  7905. {$ENDIF}
  7906.   TheHeader.Free;
  7907.   TheData.Free;
  7908. end;
  7909.  
  7910. {------------------------------------------------------------------------------
  7911.     Procedure: TCustomPlot.DoHTMLHeaderRequest
  7912.   Description: Asks the user for their HTML header data
  7913.        Author: Mat Ballard
  7914.  Date created: 09/07/2000
  7915. Date modified: 09/07/2000 by Mat Ballard
  7916.       Purpose: fires the OnHTMLHeaderRequest event
  7917.  Known Issues:
  7918.  ------------------------------------------------------------------------------}
  7919. procedure TCustomPlot.DoHTMLHeaderRequest(TheHeader: TStringList);
  7920. begin
  7921.   if assigned(FOnHTMLHeaderRequest) then
  7922.     OnHTMLHeaderRequest(Self, TheHeader);
  7923. end;
  7924.  
  7925. {------------------------------------------------------------------------------
  7926.     Procedure: TCustomPlot.CopyText
  7927.   Description: Copies data as tab-delimited text to Clipboard
  7928.        Author: Mat Ballard
  7929.  Date created: 02/25/2000
  7930. Date modified: 02/25/2000 by Mat Ballard
  7931.       Purpose: Creates a Header, fires the OnHeaderRequest event, then runs the GetData method of SeriesList
  7932.  Known Issues:
  7933.  ------------------------------------------------------------------------------}
  7934. procedure TCustomPlot.CopyText;
  7935. var
  7936.   TheStream: TMemoryStream;
  7937.   pLine: array [0..1023] of char;
  7938. {$IFDEF MSWINDOWS}
  7939.   TextPtr: Pointer;
  7940.   TextHandle: THandle;
  7941. {$ENDIF}
  7942. {$IFDEF LINUX}
  7943.   TheText: TStringList;
  7944. {$ENDIF}
  7945. begin
  7946.   StrPCopy(pLine, FTitle.Caption + CRLF);
  7947.   TheStream := TMemoryStream.Create;
  7948.   TheStream.Write(pLine, StrLen(pLine));
  7949.  
  7950.   DoHeaderRequest(TheStream);
  7951.  
  7952. {create the data in TEXT format:}
  7953.   FSeriesList.GetStream(TRUE, #9, TheStream);
  7954.  
  7955. {save it:}
  7956. {$IFDEF MSWINDOWS}
  7957.   TextHandle := GlobalAlloc(GMEM_MOVEABLE, TheStream.Size+1);
  7958.   TextPtr := GlobalLock(TextHandle);
  7959. {for some unknown reason, this Move works !}
  7960.   System.Move(TheStream.Memory^, TextPtr^, TheStream.Size);
  7961.   ClipBoard.SetAsHandle(CF_TEXT, TextHandle);
  7962.   GlobalUnlock(TextHandle);
  7963. {$ENDIF}
  7964. {$IFDEF LINUX}
  7965.   TheText := TStringList.Create;
  7966.   TheText.LoadFromStream(TheStream);
  7967.   ClipBoard.AsText := TheText.Text;
  7968.   TheText.Free;
  7969. {$ENDIF}
  7970.   TheStream.Free;
  7971. end;
  7972.  
  7973. {Copying picture to the clipboard -------------------------------------------}
  7974. {------------------------------------------------------------------------------
  7975.     Procedure: TCustomPlot.CopyBitmap
  7976.   Description: Copies a picture of the graph as a bitmap to the Clipboard
  7977.        Author: Mat Ballard
  7978.  Date created: 02/25/2000
  7979. Date modified: 02/25/2000 by Mat Ballard
  7980.       Purpose: Runs Draw method over Bitmap then copies Bitmap
  7981.  Known Issues:
  7982.  ------------------------------------------------------------------------------}
  7983. procedure TCustomPlot.CopyBitmap;
  7984. begin
  7985.   ClipBoard.Assign(Self.BitMap);
  7986. end;
  7987.  
  7988. {------------------------------------------------------------------------------
  7989.     Procedure: TCustomPlot.GetBitmap
  7990.   Description: Returns a picture of the graph as a bitmap
  7991.        Author: Mat Ballard
  7992.  Date created: 04/25/2001
  7993. Date modified: 04/25/2001 by Mat Ballard
  7994.       Purpose: Runs Draw method over Bitmap
  7995.  Known Issues:
  7996.  ------------------------------------------------------------------------------}
  7997. function TCustomPlot.GetBitmap: TBitmap;
  7998. var
  7999.   Rect: TRect;
  8000. begin
  8001.   Rect := GetClientRect;
  8002.   Result := TBitMap.Create;
  8003.   Result.Height := Rect.Bottom - Rect.Top;
  8004.   Result.Width := Rect.Right - Rect.Left;
  8005.  
  8006.   Draw(Result.Canvas);
  8007. end;
  8008.  
  8009. {------------------------------------------------------------------------------
  8010.     Procedure: TCustomPlot.SaveAsBitmap
  8011.   Description: Saves a picture of the graph as a bitmap
  8012.        Author: Mat Ballard
  8013.  Date created: 02/25/2000
  8014. Date modified: 02/25/2000 by Mat Ballard
  8015.       Purpose: Runs Draw method over Bitmap then saves Bitmap
  8016.  Known Issues:
  8017.  ------------------------------------------------------------------------------}
  8018. procedure TCustomPlot.SaveAsBitmap(
  8019.   AFileName: String);
  8020. begin
  8021.   Self.Bitmap.SaveToFile(AFileName);
  8022. end;
  8023.  
  8024. {------------------------------------------------------------------------------
  8025.      Function: TCustomPlot.GetDrawing
  8026.   Description: Returns a picture of the graph as a Windows Metafile to the Clipboard
  8027.        Author: Mat Ballard
  8028.  Date created: 05/16/2001
  8029. Date modified: 05/16/2001 by Mat Ballard
  8030.       Purpose: developer rendering image of TPlot
  8031.  Known Issues:
  8032.  ------------------------------------------------------------------------------}
  8033. {$IFDEF MSWINDOWS}
  8034. function TCustomPlot.GetDrawing: TMetafile;
  8035. var
  8036.   AMetafileCanvas: TMetafileCanvas;
  8037.   Rect: TRect;
  8038. begin
  8039.   Rect := GetClientRect;
  8040.   Result := TMetafile.Create;
  8041. {$IFDEF COMPILER3_UP}
  8042.   Result.Enhanced := TRUE;
  8043. {$ENDIF}
  8044.   Result.Height := Rect.Bottom - Rect.Top;
  8045.   Result.Width := Rect.Right - Rect.Left;
  8046.  
  8047. {$IFDEF DELPHI1}
  8048. {create the metafile canvas to draw on:}
  8049.   AMetafileCanvas :=
  8050.     TMetafileCanvas.Create(Result, 0);
  8051. {$ELSE}
  8052.   SetMetafileDescription;
  8053. {create the metafile canvas to draw on:}
  8054.   AMetafileCanvas :=
  8055.     TMetafileCanvas.CreateWithComment(Result, 0, FCreatedBy, FDescription);
  8056. {$ENDIF}
  8057.  
  8058. {draw the graph on the metafile:}
  8059.   Draw(AMetafileCanvas);
  8060.   AMetafileCanvas.Free;
  8061. end;
  8062. {$ENDIF}
  8063.  
  8064. {$IFDEF LINUX}
  8065. function TCustomPlot.GetDrawing: TDrawing;
  8066. var
  8067.   ADrawing: TDrawing;
  8068.   Rect: TRect;
  8069. begin
  8070.   Rect := GetClientRect;
  8071.   Result := TDrawing.Create;
  8072.   Result.Height := Rect.Bottom - Rect.Top;
  8073.   Result.Width := Rect.Right - Rect.Left;
  8074.  
  8075.   Draw(Result.Canvas);
  8076. end;
  8077. {$ENDIF}
  8078.  
  8079. {------------------------------------------------------------------------------
  8080.     Procedure: TCustomPlot.CopyDrawing
  8081.   Description: Copies a picture of the graph as a Windows Metafile to the Clipboard
  8082.        Author: Mat Ballard
  8083.  Date created: 02/25/2000
  8084. Date modified: 02/25/2000 by Mat Ballard
  8085.       Purpose: Runs Draw method over AMetafileCanvas then copies Metafile
  8086.  Known Issues:
  8087.  ------------------------------------------------------------------------------}
  8088. procedure TCustomPlot.CopyDrawing(Enhanced: Boolean);
  8089. {$IFDEF MSWINDOWS}
  8090. var
  8091.   AFormat: Word;
  8092.   AData: THandle;
  8093.   APalette: HPALETTE;
  8094. begin
  8095.   Self.Drawing.SaveToClipboardFormat(AFormat, AData, APalette);
  8096.   ClipBoard.SetAsHandle(AFormat, AData);
  8097. {$ENDIF}
  8098. {$IFDEF LINUX}
  8099. begin
  8100.   Clipboard.Assign(Self.Drawing);
  8101. {$ENDIF}
  8102. end;
  8103.  
  8104. {------------------------------------------------------------------------------
  8105.     Procedure: TCustomPlot.SaveAsDrawing
  8106.   Description: Saves a picture of the graph as a Windows Metafile
  8107.        Author: Mat Ballard
  8108.  Date created: 02/25/2000
  8109. Date modified: 02/25/2000 by Mat Ballard
  8110.       Purpose: Runs Draw method over Metafile Canvas then saves Metafile
  8111.  Known Issues:
  8112.  ------------------------------------------------------------------------------}
  8113. procedure TCustomPlot.SaveAsDrawing(
  8114.   AFileName: String);
  8115. begin
  8116.   Self.Drawing.SaveToFile(AFileName);
  8117. end;
  8118.  
  8119. {$IFDEF GIF}
  8120. {------------------------------------------------------------------------------
  8121.     Procedure: TCustomPlot.SaveAsGIF
  8122.   Description: Saves a picture of the graph as a GIF file
  8123.        Author: Mat Ballard
  8124.  Date created: 02/25/2000
  8125. Date modified: 02/25/2000 by Mat Ballard
  8126.       Purpose: Runs Draw method over ABitmap of AGifImage then saves AGifImage
  8127.  Known Issues: 1. Requires Anders Melander's TGifImage
  8128.                2. Package dependency problems means that it is easier to let end users add this functionality
  8129.  ------------------------------------------------------------------------------}
  8130. function TCustomPlot.GetGIF: TGIFImage;
  8131. var
  8132.   Rect: TRect;
  8133.   ABitMap: TBitMap;
  8134. begin
  8135.   Rect := GetClientRect;
  8136.   ABitMap := TBitMap.Create;
  8137.   ABitMap.PixelFormat := pf24bit;
  8138.   ABitMap.Height := Rect.Bottom - Rect.Top;
  8139.   ABitMap.Width := Rect.Right - Rect.Left;
  8140.   Self.Draw(ABitMap.Canvas);
  8141.  
  8142.   Result := TGIFImage.Create;
  8143.   Result.Assign(ABitMap);
  8144.   ABitMap.Free;
  8145. end;
  8146.  
  8147. procedure TCustomPlot.SaveAsGIF(
  8148.   AFileName: String);
  8149. begin
  8150.   Self.GIF.SaveToFile(AFileName);
  8151. end;
  8152. {$ENDIF}
  8153.  
  8154. {$IFDEF PNG}
  8155.   {$IFDEF MSWINDOWS}
  8156. function TCustomPlot.GetPNG: TPngimage;
  8157. var
  8158.   Rect: TRect;
  8159.   ABitmap: TBitmap;
  8160. begin
  8161.   Rect := GetClientRect;
  8162.   ABitmap := TBitmap.Create;
  8163. {We need 24 bit otherwise the 8 bit PNG renders white as black !}  
  8164.   ABitmap.PixelFormat := pf24bit;
  8165.   ABitmap.Height := Rect.Bottom - Rect.Top;
  8166.   ABitmap.Width := Rect.Right - Rect.Left;
  8167.   Draw(ABitmap.Canvas);
  8168.  
  8169.   Result := TPngimage.Create;
  8170.   Result.Title := FTitle.Caption;
  8171.   Result.Author := FCreatedBy;
  8172.   Result.Description := FDescription;
  8173.   Result.Software := ExtractFileName(Application.ExeName);
  8174.   Result.CopyFromBmp(ABitmap);
  8175.   ABitmap.Free;
  8176. end;
  8177.   {$ENDIF}
  8178.   {$IFDEF LINUX}
  8179. function TCustomPlot.GetPNG: TBitmap;
  8180. var
  8181.   Rect: TRect;
  8182. begin
  8183.   Rect := GetClientRect;
  8184.   Result := TBitMap.Create;
  8185.   Result.Format := 'PNG';
  8186.   Result.Height := Rect.Bottom - Rect.Top;
  8187.   Result.Width := Rect.Right - Rect.Left;
  8188.  
  8189.   Draw(Result.Canvas);
  8190. end;
  8191.   {$ENDIF}
  8192. {------------------------------------------------------------------------------
  8193.     Procedure: TCustomPlot.SaveAsPNG
  8194.   Description: Saves a picture of the graph as a PNG file
  8195.        Author: Mat Ballard
  8196.  Date created: 02/25/2000
  8197. Date modified: 02/25/2000 by Mat Ballard
  8198.       Purpose: Runs Draw method over ABitmap of APngImage then saves APngImage
  8199.  Known Issues:
  8200.  ------------------------------------------------------------------------------}
  8201. procedure TCustomPlot.SaveAsPng(
  8202.   AFileName: String);
  8203. begin
  8204.   Self.Png.SaveToFile(AFileName);
  8205. end;
  8206. {$ENDIF}
  8207.  
  8208. {------------------------------------------------------------------------------
  8209.     Procedure: TCustomPlot.SetAsNormalClick
  8210.   Description: Defines the current view == Mins and Maxes of axes, as the Normal view.
  8211.        Author: Mat Ballard
  8212.  Date created: 08/12/2000
  8213. Date modified: 08/12/2000 by Mat Ballard
  8214.       Purpose: Zoom == Axis Min/Max management
  8215.  Known Issues:
  8216.  ------------------------------------------------------------------------------}
  8217. procedure TCustomPlot.SetAsNormalClick(Sender: TObject);
  8218. var
  8219.   i: Integer;
  8220.   pTheAxis: TAxis;
  8221. begin
  8222.   for i := 0 to FAxisList.Count-1 do
  8223.   begin
  8224.     pTheAxis := TAxis(FAxisList.Items[i]);
  8225.     pTheAxis.ZoomIntercept := pTheAxis.Intercept;
  8226.     pTheAxis.ZoomMin := pTheAxis.Min;
  8227.     pTheAxis.ZoomMax := pTheAxis.Max;
  8228.   end;
  8229.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormalView)].Enabled := TRUE;
  8230. end;
  8231.  
  8232. {------------------------------------------------------------------------------
  8233.     Procedure: TCustomPlot.NormalViewClick
  8234.   Description: Zooms to the Normal view
  8235.        Author: Mat Ballard
  8236.  Date created: 08/12/2000
  8237. Date modified: 08/12/2000 by Mat Ballard
  8238.       Purpose: Zoom == Axis Min/Max management
  8239.  Known Issues:
  8240.  ------------------------------------------------------------------------------}
  8241. procedure TCustomPlot.NormalViewClick(Sender: TObject);
  8242. var
  8243.   i: Integer;
  8244.   pTheAxis: TAxis;
  8245. begin
  8246.   for i := 0 to FAxisList.Count-1 do
  8247.   begin
  8248.     pTheAxis := TAxis(FAxisList.Items[i]);
  8249.     if (pTheAxis.ZoomMin < pTheAxis.ZoomMax) then
  8250.     begin
  8251.       pTheAxis.Min := pTheAxis.ZoomMin;
  8252.       pTheAxis.Max := pTheAxis.ZoomMax;
  8253.       pTheAxis.Intercept := pTheAxis.ZoomIntercept;
  8254.     end;
  8255.   end;
  8256. end;
  8257.  
  8258. {------------------------------------------------------------------------------
  8259.     Procedure: TCustomPlot.ManualZoomClick
  8260.   Description: Manually Zooms In
  8261.        Author: Mat Ballard
  8262.  Date created: 02/25/2000
  8263. Date modified: 02/25/2000 by Mat Ballard
  8264.       Purpose: Runs the ZoomForm and adjusts Axes accordingly
  8265.  Known Issues:
  8266.  ------------------------------------------------------------------------------}
  8267. procedure TCustomPlot.ManualZoomClick(Sender: TObject);
  8268. var
  8269.   ZoomForm: TZoomForm;
  8270.   i,
  8271.   PixelYMin,
  8272.   PixelYMax: Integer;
  8273.   pTheYAxis: TAxis;
  8274. begin
  8275.   ZoomForm := TZoomForm.Create(Self);
  8276.   with ZoomForm do
  8277.   begin
  8278.     XMinNEdit.AsReal := FXAxis.Min;
  8279.     XMaxNEdit.AsReal := FXAxis.Max;
  8280.     YMinNEdit.AsReal := FYAxis.Min;
  8281.     YMaxNEdit.AsReal := FYAxis.Max;
  8282.  
  8283.     ZoomForm.HelpFile := FHelpFile;
  8284.  
  8285.     if (ShowModal = mrOK) then
  8286.     begin
  8287.       FXAxis.Min := XMinNEdit.AsReal;
  8288.       FXAxis.Max := XMaxNEdit.AsReal;
  8289.       FYAxis.Min := YMinNEdit.AsReal;
  8290.       FYAxis.Max := YMaxNEdit.AsReal;
  8291.       PixelYMin := FYAxis.FofY(FYAxis.Min);
  8292.       PixelYMax := FYAxis.FofY(FYAxis.Max);
  8293.       for i := 2 to FAxisList.Count-1 do
  8294.       begin
  8295.         pTheYAxis := TAxis(FAxisList[i]);
  8296.         pTheYAxis.Min := pTheYAxis.YofF(PixelYMin);
  8297.         pTheYAxis.Max := pTheYAxis.YofF(PixelYMax);
  8298.       end;
  8299.     end;
  8300.   end;
  8301.   ZoomForm.Free;
  8302.   Refresh;
  8303. end;
  8304.  
  8305. {------------------------------------------------------------------------------
  8306.     Procedure: TCustomPlot.ZoomOutClick
  8307.   Description: Zooms out after Zooming In
  8308.        Author: Mat Ballard
  8309.  Date created: 02/25/2000
  8310. Date modified: 02/25/2000 by Mat Ballard
  8311.       Purpose: Resets the axes Min and Max values to those of the Axis
  8312.  Known Issues:
  8313.  ------------------------------------------------------------------------------}
  8314. procedure TCustomPlot.ZoomOutClick(Sender: TObject);
  8315. var
  8316.   i: Integer;
  8317.   pSeries: TSeries;
  8318. begin
  8319.   FXAxis.Min := FSeriesList.Xmin;
  8320.   FXAxis.Max := FSeriesList.Xmax;
  8321.   FYAxis.Intercept := FXAxis.Min;
  8322. {  for i := 1 to FAxisList.Count-1 do
  8323.   begin
  8324.     TAxis(FAxisList[i]).Visible := FALSE;
  8325.   end;}
  8326.  
  8327.   case FPlotType of
  8328.     ptXY, ptMultiple:
  8329.       begin
  8330.         for i := 0 to FSeriesList.Count-1 do
  8331.         begin
  8332.           pSeries := FSeriesList[i];
  8333.           pSeries.YAxis.Min := pSeries.YMin;
  8334.           pSeries.YAxis.Max := pSeries.YMax;
  8335.           {if (pSeries.YAxis.Min > Round(pSeries.YMin - 0.999)) then
  8336.             pSeries.YAxis.Min := Round(pSeries.YMin - 0.999);
  8337.           if (pSeries.YAxis.Max < Round(pSeries.YMax + 0.999)) then
  8338.             pSeries.YAxis.Max := Round(pSeries.YMax + 0.999);}
  8339.         end;
  8340.       end;
  8341.  
  8342.     ptError, ptBubble:
  8343.       begin
  8344.         for i := 0 to FSeriesList.Count-1 do
  8345.         begin
  8346.           if ((i mod 2) = 0) then
  8347.           begin {odd series are just error - not values}
  8348.             pSeries := FSeriesList[i];
  8349.             pSeries.YAxis.Min := pSeries.YMin;
  8350.             pSeries.YAxis.Max := pSeries.YMax;
  8351.             {if (pSeries.YAxis.Min > Round(FSeriesList.YErrorMin - 0.999)) then
  8352.               pSeries.YAxis.Min := Round(FSeriesList.YErrorMin - 0.999);
  8353.             if (pSeries.YAxis.Max < Round(FSeriesList.YErrorMax + 0.999)) then
  8354.               pSeries.YAxis.Max := Round(FSeriesList.YErrorMax + 0.999);}
  8355.           end;
  8356.         end;
  8357.       end;
  8358.  
  8359.     ptColumn:
  8360.       begin
  8361.         for i := 1 to FAxisList.Count-1 do
  8362.           TAxis(FAxisList[i]).Min := 0;
  8363.         for i := 0 to FSeriesList.Count-1 do
  8364.         begin
  8365.           pSeries := FSeriesList[i];
  8366.           if (pSeries.YAxis.Max < Round(pSeries.YMax + 0.999)) then
  8367.             pSeries.YAxis.Max := Round(pSeries.YMax + 0.999);
  8368.         end;
  8369.       end;
  8370.  
  8371.     ptStack:
  8372.       begin
  8373.         YAxis.Min := 0;
  8374.         if (FSeriesList.TotalNoPts > 0) then
  8375.           YAxis.Max := Round(FSeriesList.Count * FSeriesList.Ymax + 0.999);
  8376.       end;
  8377.  
  8378.     ptNormStack:
  8379.       begin
  8380.         for i := 1 to FAxisList.Count-1 do
  8381.         begin
  8382.           TAxis(FAxisList[i]).Min := 0;
  8383.           TAxis(FAxisList[i]).Max := 100;
  8384.         end;
  8385.       end;
  8386.       
  8387.     ptPolar:
  8388.       begin
  8389.         FXAxis.Min := Round(FSeriesList.Xmin - 0.999);
  8390.         FXAxis.Max := Round(FSeriesList.Xmax + 0.999);
  8391.         FYAxis.Min := Round(FSeriesList.Ymin - 0.999);
  8392.         FYAxis.Max := Round(FSeriesList.Ymax + 0.999);
  8393.         if (FXAxis.Min > -FXAxis.Max) then
  8394.           FXAxis.Min := -FXAxis.Max;
  8395.         if (FXAxis.Max < -FXAxis.Min) then
  8396.           FXAxis.Max := -FXAxis.Min;
  8397.         if (FYAxis.Min > -FYAxis.Max) then
  8398.           FYAxis.Min := -FYAxis.Max;
  8399.         if (FYAxis.Max < -FYAxis.Min) then
  8400.           FYAxis.Max := -FYAxis.Min;
  8401.         FXAxis.Intercept := 0;
  8402.         FYAxis.Intercept := 0;
  8403.       end;
  8404.  
  8405.     pt3DContour, pt3DWire:
  8406.       begin
  8407.         FYAxis.Min := FSeriesList.Ymin;
  8408.         FYAxis.Max := FSeriesList.Ymax;
  8409.         FZAxis.Min := FSeriesList.Zmin;
  8410.         FZAxis.Max := FSeriesList.Zmax;
  8411.       end;
  8412.   end; {case}
  8413.   FXAxis.Intercept := FYAxis.Min;
  8414.  
  8415.   DestroyPageButtons;
  8416.  
  8417.   DoStyleChange(Self);
  8418. end;
  8419.  
  8420. {------------------------------------------------------------------------------
  8421.     Procedure: TCustomPlot.CopyHTMLClick
  8422.   Description: copys the data as HTML
  8423.        Author: Mat Ballard
  8424.  Date created: 04/25/2000
  8425. Date modified: 04/25/2000 by Mat Ballard
  8426.       Purpose: ... in CF_TEXT format
  8427.  Known Issues:
  8428.  ------------------------------------------------------------------------------}
  8429. procedure TCustomPlot.CopyHTMLClick(Sender: TObject);
  8430. begin
  8431.   CopyHTML(CF_TEXT);
  8432. end;
  8433.  
  8434. {------------------------------------------------------------------------------
  8435.     Procedure: TCustomPlot.HandleClick
  8436.   Description: fires the OnClick event of the menuitem with Tag Tag
  8437.        Author: Mat Ballard
  8438.  Date created: 04/25/2000
  8439. Date modified: 04/25/2000 by Mat Ballard
  8440.       Purpose: allows the TPlotMenu component to function
  8441.  Known Issues:
  8442.  ------------------------------------------------------------------------------}
  8443. procedure TCustomPlot.HandleClick(Sender: TObject; TheTag: Integer);
  8444. var
  8445.   i, j: Integer;
  8446. begin
  8447. {needed to handle Mode and Direction:}
  8448.   FMenuTag := TheTag;
  8449.   if (GetIndicesFromTag(TheTag, i, j)) then
  8450. {$IFDEF COMPILER2_UP}
  8451.     if Assigned(FPlotPopUpMenu.Items[i].Items[j].OnClick) then
  8452. {$ENDIF}
  8453.       FPlotPopUpMenu.Items[i].Items[j].OnClick(Sender);
  8454. end;
  8455.  
  8456. {------------------------------------------------------------------------------
  8457.     Procedure: TCustomPlot.GetIndicesFromTag
  8458.   Description: Gets the i and j indices from the Tag
  8459.        Author: Mat Ballard
  8460.  Date created: 05/25/2000
  8461. Date modified: 05/25/2000 by Mat Ballard
  8462.       Purpose: interfacing with external components
  8463.  Known Issues:
  8464.  ------------------------------------------------------------------------------}
  8465. function TCustomPlot.GetIndicesFromTag(TheTag: Integer; var i, j: Integer): Boolean;
  8466. var
  8467.   MenuIndex: Integer;
  8468.   TheResult: Boolean;
  8469. begin
  8470. {TPlotToolBar throws some strange tags at this function:
  8471.   if (TheTag <= TAG_BASE) then raise
  8472.     ERangeError.CreateFmt('GetIndicesFromTag: ' + sInvalidTag, [Tag]);}
  8473.  
  8474.   TheResult := FALSE;
  8475.  
  8476.   MenuIndex := TheTag - TAG_BASE - Ord(High(TMainMenus)){mnuCalc} - 2;
  8477.   if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TFileMenus)){mnuPrint})) then
  8478.   begin
  8479.     i := 0;
  8480.     j := MenuIndex;
  8481.     TheResult := TRUE;
  8482.   end
  8483.   else
  8484.   begin
  8485.     MenuIndex := MenuIndex - Ord(High(TFileMenus)){mnuPrint} - 1;
  8486.     if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TEditMenus)))) then
  8487.     begin
  8488.       i := 1;
  8489.       j := MenuIndex;
  8490.       TheResult := TRUE;
  8491.     end
  8492.     else
  8493.     begin
  8494.       MenuIndex := MenuIndex - Ord(High(TEditMenus)){mnuEditProperties} - 1;
  8495.       if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TViewMenus)))) then
  8496.       begin
  8497.         i := 2;
  8498.         j := MenuIndex;
  8499.         TheResult := TRUE;
  8500.       end
  8501.       else
  8502.       begin
  8503.         MenuIndex := MenuIndex - Ord(High(TViewMenus)){mnuZoomOut} - 1;
  8504.         if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TCalcMenus)))) then
  8505.         begin
  8506.           i := 3;
  8507.           j := MenuIndex;
  8508.           TheResult := TRUE;
  8509.         end;
  8510.       end;
  8511.     end;
  8512.   end;
  8513.   GetIndicesFromTag := TheResult;
  8514. {$IFDEF DELPHI3_UP}
  8515.   if (TheResult) then
  8516.     Assert(FPlotPopUpMenu.Items[i].Items[j].Tag = TheTag,
  8517.       'TCustomPlot.GetIndicesFromTag: ' + sTagNotMatch);
  8518. {$ENDIF}
  8519. end;
  8520.  
  8521. {------------------------------------------------------------------------------
  8522.     Procedure: TCustomPlot.DisplaceClick
  8523.   Description: runs the "Displacement" dialog box
  8524.        Author: Mat Ballard
  8525.  Date created: 04/25/2000
  8526. Date modified: 04/25/2000 by Mat Ballard
  8527.       Purpose: responds to "Displace" menu selection
  8528.  Known Issues:
  8529.  ------------------------------------------------------------------------------}
  8530. procedure TCustomPlot.DisplaceClick(Sender: TObject);
  8531. begin
  8532.   if (GetSeriesFromUser) then
  8533.   begin
  8534.     pSeries.Displace(FHelpFile);
  8535.     DoStyleChange(Self);
  8536.   end;
  8537.   ZeroScreenStuff;
  8538. end;
  8539.  
  8540. {------------------------------------------------------------------------------
  8541.     Procedure: TCustomPlot.ZoomInClick
  8542.   Description: Zooms in using the mouse
  8543.        Author: Mat Ballard
  8544.  Date created: 04/25/2000
  8545. Date modified: 05/30/2001 by Mat Ballard
  8546.       Purpose: responds to "Zoom In" menu selection
  8547.  Known Issues:
  8548.  ------------------------------------------------------------------------------}
  8549. procedure TCustomPlot.ZoomInClick(Sender: TObject);
  8550. var
  8551.   i: Integer;
  8552.   NewMin: Single;
  8553. begin
  8554.   if ((FScreenJob = sjRightDrag) or
  8555.       (FScreenJob = sjZoomIn)) then
  8556.   begin
  8557.     NewMin := FXAxis.XofF(Selection.Left);
  8558.     FXAxis.SetMinMaxFromSeries(NewMin, FXAxis.XofF(Selection.Right));
  8559.     for i := 1 to FAxisList.Count-1 do
  8560.     begin
  8561.       TAxis(FAxisList[i]).AutoScale := TRUE;
  8562.       NewMin := TAxis(FAxisList[i]).YofF(Selection.Bottom);
  8563.       FYAxis.SetMinMaxFromSeries(NewMin, TAxis(FAxisList[i]).YofF(Selection.Top));
  8564.     end;
  8565.     CreatePageButtons;
  8566.     ZeroScreenStuff;
  8567.   end
  8568.   else
  8569.   begin
  8570.     FInstructions.Clear;
  8571.     FInstructions.Add(sZoomIn);
  8572.     FScreenJob := sjZoomIn;
  8573.     DoStyleChange(Self);
  8574.   end;
  8575. end;
  8576.  
  8577. {------------------------------------------------------------------------------
  8578.     Procedure: TCustomPlot.DifferentiateClick
  8579.   Description: Replaces the selected Axis with its differential
  8580.        Author: Mat Ballard
  8581.  Date created: 04/25/2000
  8582. Date modified: 04/25/2000 by Mat Ballard
  8583.       Purpose: responds to "Differential" menu selection
  8584.  Known Issues:
  8585.  ------------------------------------------------------------------------------}
  8586. procedure TCustomPlot.DifferentiateClick(Sender: TObject);
  8587. begin
  8588.   if (GetSeriesFromUser) then
  8589.   begin
  8590.     pSeries.Differentiate;
  8591.     ZoomOutClick(Self);
  8592.   end;
  8593.   ZeroScreenStuff;
  8594. end;
  8595.  
  8596. {------------------------------------------------------------------------------
  8597.     Procedure: TCustomPlot.IntegrateClick
  8598.   Description: Replaces the selected Axis with its differential
  8599.        Author: Mat Ballard
  8600.  Date created: 04/25/2000
  8601. Date modified: 04/25/2000 by Mat Ballard
  8602.       Purpose: responds to "Integrate" menu selection
  8603.  Known Issues:
  8604.  ------------------------------------------------------------------------------}
  8605. procedure TCustomPlot.IntegrateClick(Sender: TObject);
  8606. begin
  8607.   if (GetSeriesFromUser) then
  8608.   begin
  8609.     pSeries.Integrate;
  8610.     ZoomOutClick(Self);
  8611.   end;
  8612.   ZeroScreenStuff;
  8613. end;
  8614.  
  8615. {------------------------------------------------------------------------------
  8616.     Procedure: TCustomPlot.IntegralClick
  8617.   Description: calculates the integral of the selected Series over a selected range
  8618.        Author: Mat Ballard
  8619.  Date created: 04/25/2000
  8620. Date modified: 05/30/2001 by Mat Ballard
  8621.       Purpose: responds to "Integral" menu selection
  8622.  Known Issues:
  8623.  ------------------------------------------------------------------------------}
  8624. procedure TCustomPlot.IntegralClick(Sender: TObject);
  8625. var
  8626.   Msg: String;
  8627.   Sum,
  8628.   TheLeft,
  8629.   TheRight: Single;
  8630. begin
  8631.   if (GetSeriesFromUser) then
  8632.   begin
  8633.     if ((FScreenJob = sjRightDrag) or
  8634.         (FScreenJob = sjIntegral)) then
  8635.     begin
  8636.       TheLeft := FXAxis.XofF(Selection.Left);
  8637.       TheRight := FXAxis.XofF(Selection.Right);
  8638.       Sum := pSeries.Integral(TheLeft, TheRight);
  8639.       Msg := sIntegral1 + pSeries.Name + sFrom + CRLF;
  8640.       Msg := Msg + FXAxis.LabelToStrF(TheLeft) + sTo +
  8641.         FXAxis.LabelToStrF(TheRight);
  8642.       if (Length(FXAxis.Title.Units) > 0) then
  8643.         Msg := Msg + ' ' + FXAxis.Title.Units;
  8644.       Msg := Msg + sIs + CRLF +
  8645.         Format('%g', [Sum]);
  8646.       if ((Length(FXAxis.Title.Units) > 0) and
  8647.           (Length(pSeries.YAxis.Title.Units) > 0)) then
  8648.       begin
  8649.         Msg := Msg + ' (' + pSeries.YAxis.Title.Units + '.' +
  8650.           FXAxis.Title.Units + ')';
  8651.       end
  8652.       else if (Length(FXAxis.Title.Units) > 0) then
  8653.       begin
  8654.         Msg := Msg + ' (' + FXAxis.Title.Units + ')';
  8655.       end
  8656.       else if (Length(pSeries.YAxis.Title.Units) > 0) then
  8657.       begin
  8658.         Msg := Msg + ' (' + pSeries.YAxis.Title.Units + ')';
  8659.       end;
  8660.       ShowMessage(Msg);
  8661.       ClipBoard.AsText := Msg;
  8662.       ZeroScreenStuff;
  8663.     end
  8664.     else
  8665.     begin
  8666.       FScreenJob := sjIntegral;
  8667.       FInstructions.Clear;
  8668.       FInstructions.Add(sIntegral2);
  8669.       DoStyleChange(Self);
  8670.     end;
  8671.   end;
  8672. end;
  8673.  
  8674. {------------------------------------------------------------------------------
  8675.      Function: TCustomPlot.GetClickAndDragDelay
  8676.   Description: standard property Get function
  8677.        Author: Mat Ballard
  8678.  Date created: 04/25/2000
  8679. Date modified: 04/25/2000 by Mat Ballard
  8680.       Purpose: gets the value of the ClickAndDragDelay Property
  8681.  Return value: Integer
  8682.  Known Issues:
  8683.  ------------------------------------------------------------------------------}
  8684. function TCustomPlot.GetClickAndDragDelay: Integer;
  8685. begin
  8686.   GetClickAndDragDelay := MouseTimer.Interval;
  8687. end;
  8688.  
  8689. {------------------------------------------------------------------------------
  8690.     Procedure: TCustomPlot.ZeroScreenStuff
  8691.   Description: cleans up after a menu event handler - XXXClick
  8692.        Author: Mat Ballard
  8693.  Date created: 04/25/2000
  8694. Date modified: 04/25/2000 by Mat Ballard
  8695.       Purpose: mouse management
  8696.  Known Issues:
  8697.  ------------------------------------------------------------------------------}
  8698. procedure TCustomPlot.ZeroScreenStuff;
  8699. begin
  8700.   FScreenJob := sjNone;
  8701.   ClickedObjectType := soNone;
  8702.   pClickedObject := nil;
  8703.   SecondClickedObjectType := soNone;
  8704.   pSecondClickedObject := nil;
  8705.   TheSeries := -1;
  8706.   pSeries := nil;
  8707.   TheAxis := -1;
  8708.   pAxis := nil;
  8709.   FOnSelection := nil;
  8710.   FOnDualSelection := nil;
  8711.   Screen.Cursor := crDefault;
  8712. end;
  8713.  
  8714. {------------------------------------------------------------------------------
  8715.     Procedure: TCustomPlot.HighsClick
  8716.   Description: Calculates the Highs (peaks) and/or Lows (troughs) of a series
  8717.        Author: Mat Ballard
  8718.  Date created: 09/25/2000
  8719. Date modified: 09/25/2000 by Mat Ballard
  8720.       Purpose: data processing
  8721.  Known Issues:
  8722.  ------------------------------------------------------------------------------}
  8723. procedure TCustomPlot.HighsClick(Sender: TObject);
  8724. var
  8725.   OptionsDlg: TOptionsDlg;
  8726. begin
  8727.   if (GetSeriesFromUser) then
  8728.   begin
  8729.     OptionsDlg := TOptionsDlg.Create(nil);
  8730.     with OptionsDlg do
  8731.     begin
  8732.       FormTitle := sHighLow1;
  8733.       Question := sHighLow2;
  8734.       OptionList.Add(sHighLow3);
  8735.       OptionList.Add(sHighLow4);
  8736.       OptionList.Add(sHighLow5);
  8737.       OptionList.Add(sHighLow6);
  8738.       case Execute of
  8739.         1: pSeries.ClearHighsLows;
  8740.         2:
  8741.           begin
  8742.             pSeries.FindHighsLows(0, pSeries.NoPts, 5);
  8743.             pSeries.HighLow := pSeries.HighLow + [hlHigh];
  8744.           end;
  8745.         3:
  8746.           begin
  8747.             pSeries.FindHighsLows(0, pSeries.NoPts, 5);
  8748.             pSeries.HighLow := pSeries.HighLow + [hlLow];
  8749.           end;
  8750.         4:
  8751.           begin
  8752.             pSeries.FindHighsLows(0, pSeries.NoPts, 5);
  8753.             pSeries.HighLow := pSeries.HighLow + [hlLow, hlHigh];
  8754.           end;
  8755.       end;
  8756.     end;
  8757.     OptionsDlg.Free;
  8758.  
  8759.     DoStyleChange(Self);
  8760.   end;
  8761.   ZeroScreenStuff;
  8762. end;
  8763.  
  8764. {------------------------------------------------------------------------------
  8765.     Procedure: TCustomPlot.MovingAverageClick
  8766.   Description: Calculates and displays the Moving Average of a series
  8767.        Author: Mat Ballard
  8768.  Date created: 09/25/2000
  8769. Date modified: 09/25/2000 by Mat Ballard
  8770.       Purpose: data smoothing
  8771.  Known Issues:
  8772.  ------------------------------------------------------------------------------}
  8773. procedure TCustomPlot.MovingAverageClick(Sender: TObject);
  8774. var
  8775.   Span: Integer;
  8776.   SpanStr: String;
  8777. begin
  8778.   if (GetSeriesFromUser) then
  8779.   begin
  8780.     SpanStr := '10';
  8781.     if (InputQuery(sMovingAverage1, sMovingAverage2, SpanStr)) then
  8782.     begin
  8783.       try
  8784.         Span := StrToInt(SpanStr);
  8785.         pSeries.MovingAverage(Span);
  8786.       except
  8787.         ShowMessage(sMovingAverage1);
  8788.       end;
  8789.     end;
  8790.     DoStyleChange(Self);
  8791.   end;
  8792.   ZeroScreenStuff;
  8793. end;
  8794.  
  8795. {------------------------------------------------------------------------------
  8796.     Procedure: TCustomPlot.AverageClick
  8797.   Description: Calculates the Average of a series over a range
  8798.        Author: Mat Ballard
  8799.  Date created: 09/25/2000
  8800. Date modified: 05/30/2001 by Mat Ballard
  8801.       Purpose: data processing
  8802.  Known Issues:
  8803.  ------------------------------------------------------------------------------}
  8804. procedure TCustomPlot.AverageClick(Sender: TObject);
  8805. var
  8806.   Msg: String;
  8807.   Sum,
  8808.   TheLeft,
  8809.   TheRight: Single;
  8810. begin
  8811.   if (GetSeriesFromUser) then
  8812.   begin
  8813.     if ((FScreenJob = sjRightDrag) or
  8814.         (FScreenJob = sjAverage)) then
  8815.     begin
  8816.       TheLeft := FXAxis.XofF(Selection.Left);
  8817.       TheRight := FXAxis.XofF(Selection.Right);
  8818.       Sum := pSeries.Average(TheLeft, TheRight);
  8819.       Msg := sAverage1 + pSeries.Name + sFrom + CRLF;
  8820.       Msg := Msg + FXAxis.LabelToStrF(TheLeft) + sTo +
  8821.         FXAxis.LabelToStrF(TheRight);
  8822.       if (Length(FXAxis.Title.Units) > 0) then
  8823.         Msg := Msg + ' ' + FXAxis.Title.Units;
  8824.       Msg := Msg + sIs + CRLF +
  8825.         Format('%g', [Sum]);
  8826.       if (Length(pSeries.YAxis.Title.Units) > 0) then
  8827.       begin
  8828.         Msg := Msg + ' (' + pSeries.YAxis.Title.Units + ')';
  8829.       end;
  8830.       ShowMessage(Msg);
  8831.       ClipBoard.AsText := Msg;
  8832.       ZeroScreenStuff;
  8833.     end
  8834.     else
  8835.     begin
  8836.       FScreenJob := sjAverage;
  8837.       FInstructions.Clear;
  8838.       FInstructions.Add(sAverage2);
  8839.       DoStyleChange(Self);
  8840.     end;
  8841.   end;
  8842. end;
  8843.  
  8844. {------------------------------------------------------------------------------
  8845.     Procedure: TCustomPlot.LinearizeClick
  8846.   Description: Linearizes Y data of a series over a range
  8847.        Author: Mat Ballard
  8848.  Date created: 05/30/2001
  8849. Date modified: 05/30/2001 by Mat Ballard
  8850.       Purpose: data processing
  8851.  Known Issues:
  8852.  ------------------------------------------------------------------------------}
  8853. procedure TCustomPlot.LinearizeClick(Sender: TObject);
  8854. var
  8855.   TheLeft,
  8856.   TheRight: Single;
  8857. begin
  8858.   if (GetSeriesFromUser) then
  8859.   begin
  8860.     if ((FScreenJob = sjRightDrag) or
  8861.         (FScreenJob = sjLinearize)) then
  8862.     begin
  8863.       TheLeft := FXAxis.XofF(Selection.Left);
  8864.       TheRight := FXAxis.XofF(Selection.Right);
  8865.       pSeries.Linearize(TheLeft, TheRight);
  8866.       ZeroScreenStuff;
  8867.       Refresh;
  8868.     end
  8869.     else
  8870.     begin
  8871.       FScreenJob := sjLinearize;
  8872.       FInstructions.Clear;
  8873.       FInstructions.Add(sLinearize);
  8874.       DoStyleChange(Self);
  8875.     end;
  8876.   end;
  8877. end;
  8878.  
  8879. {------------------------------------------------------------------------------
  8880.     Procedure: TCustomPlot.ZeroClick
  8881.   Description: Calculates the Zero of a series over a range
  8882.        Author: Mat Ballard
  8883.  Date created: 05/30/2001
  8884. Date modified: 05/30/2001 by Mat Ballard
  8885.       Purpose: data processing
  8886.  Known Issues:
  8887.  ------------------------------------------------------------------------------}
  8888. procedure TCustomPlot.ZeroClick(Sender: TObject);
  8889. var
  8890.   TheLeft,
  8891.   TheRight: Single;
  8892. begin
  8893.   if (GetSeriesFromUser) then
  8894.   begin
  8895.     if ((FScreenJob = sjRightDrag) or
  8896.         (FScreenJob = sjZero)) then
  8897.     begin
  8898.       TheLeft := FXAxis.XofF(Selection.Left);
  8899.       TheRight := FXAxis.XofF(Selection.Right);
  8900.       pSeries.Zero(TheLeft, TheRight);
  8901.       ZeroScreenStuff;
  8902.       Refresh;
  8903.     end
  8904.     else
  8905.     begin
  8906.       FScreenJob := sjZero;
  8907.       FInstructions.Clear;
  8908.       FInstructions.Add(sZero);
  8909.       DoStyleChange(Self);
  8910.     end;
  8911.   end;
  8912. end;
  8913.  
  8914. {------------------------------------------------------------------------------
  8915.     Procedure: TCustomPlot.NewAxisClick
  8916.   Description: Adds a new axis, based on either the selected or last axis.
  8917.        Author: Mat Ballard
  8918.  Date created: 06/12/2000
  8919. Date modified: 06/12/2000 by Mat Ballard
  8920.       Purpose: axis management
  8921.  Known Issues:
  8922.  ------------------------------------------------------------------------------}
  8923. procedure TCustomPlot.NewAxisClick(Sender: TObject);
  8924. var
  8925.   TheTemplate: Integer;
  8926.   NewAxis: TAxis;
  8927. begin
  8928. {has the user already selected an object ?}
  8929. {see GetTheClickedObject and ZeroScreenStuff}
  8930.   TheTemplate := TheAxis;
  8931.   if (TheTemplate <= 0) then
  8932.     TheTemplate := FAxisList.Count - 1;
  8933. {NB: there is only ONE X Axis, otherwise things get TOO complicated,
  8934.  so if the user right-clicks on the X Axis, it is effectively ignored}
  8935.  
  8936.   NewAxis := TAxis.Create(Self);
  8937.   FAxisList.Add(NewAxis);
  8938.   NewAxis.Assign(TAxis(FAxisList[TheTemplate]));
  8939.   NewAxis.OnChange := DoStyleChange;
  8940.  
  8941. {Move the new axis to the right:}
  8942.   if (FAxisList.Count = 3) then
  8943.   begin
  8944. {this new one is a secondary axis:}
  8945.     NewAxis.AxisType := atSecondary;
  8946.     NewAxis.Intercept := FXAxis.Max;
  8947.     NewAxis.TickDirection := orRight;
  8948.     NewAxis.Title.Orientation := orRight;
  8949.   end
  8950.   else
  8951.   begin
  8952.     NewAxis.AxisType := atTertiary;
  8953. {place the new axis half-way between the last and the right hand side:}
  8954.     NewAxis.Intercept := FXAxis.XofF((NewAxis.MidX + Width) div 2);
  8955.   end;
  8956.  
  8957. {if this over-runs the panel width, then wrap around:}
  8958.   if (NewAxis.Left > Width) then
  8959.     NewAxis.Left := NewAxis.Left - Width;
  8960.  
  8961. {... and rename it:}
  8962.   NewAxis.Name := sCopyOf + NewAxis.Name;
  8963.   NewAxis.Title.Caption := sCopyOf + NewAxis.Title.Caption;
  8964.   NewAxis.Tag := Ord(soYAxis);
  8965.   NewAxis.Labels.Tag := Ord(soYAxisLabel);
  8966.   NewAxis.Title.Tag := Ord(soYAxisTitle);
  8967.  
  8968. {add this New Y Axis to the ScreenObjectList:}
  8969.   ScreenObjectList.Insert(Ord(soLeftBorder), NewAxis.Labels);
  8970.   ScreenObjectList.Insert(Ord(soLeftBorder), NewAxis.Title);
  8971.   ScreenObjectList.Insert(Ord(soLeftBorder), NewAxis);
  8972.   //Inc(NoBasicScreenObjects, 3);
  8973. {note that we insert: we do this in order to make Y Axes be found before
  8974.  borders and series.}
  8975.  
  8976. {re-initialize:}
  8977.   ZeroScreenStuff;
  8978. {we need to call re-size to force a SetAxisDimensions:}
  8979.   Resize;
  8980.   DoStyleChange(Self);
  8981. end;
  8982.  
  8983. {------------------------------------------------------------------------------
  8984.     Procedure: TCustomPlot.DeleteAxisClick
  8985.   Description: Deletes an axis
  8986.        Author: Mat Ballard
  8987.  Date created: 06/12/2000
  8988. Date modified: 06/12/2000 by Mat Ballard
  8989.       Purpose: axis management
  8990.  Known Issues:
  8991.  ------------------------------------------------------------------------------}
  8992. procedure TCustomPlot.DeleteAxisClick(Sender: TObject);
  8993. begin
  8994.   if (GetAxisFromUser(2)) then
  8995.     DeleteAxis(TheAxis, TRUE);
  8996. end;
  8997.  
  8998. {------------------------------------------------------------------------------
  8999.      Function: TCustomPlot.DeleteAxis
  9000.   Description: Deletes the selected axis
  9001.        Author: Mat Ballard
  9002.  Date created: 04/25/2000
  9003. Date modified: 04/25/2000 by Mat Ballard
  9004.       Purpose: axis management
  9005.  Known Issues:
  9006.  ------------------------------------------------------------------------------}
  9007. procedure TCustomPlot.DeleteAxis(Index: Integer; Confirm: Boolean);
  9008. var
  9009.   pAxisToDelete: TAxis;
  9010. begin
  9011.   if ((Index <= 1) or
  9012.       (Index >= FAxisList.Count)) then raise
  9013.     ERangeError.CreateFmt(sDeleteAxis1, [Index, FAxisList.Count-1]);
  9014.  
  9015.   pAxisToDelete := TAxis(FAxisList[Index]);
  9016.  
  9017.   if (Confirm) then
  9018.   begin
  9019.     {Confirm := (IDNO = MessageBox(0,
  9020.       'Are you sure you want to delete' + pAxisToDelete.Title.Caption,
  9021.       'Delete Secondary Axis',
  9022.       MB_YESNO + MB_ICONQUESTION));}
  9023.     Confirm := (mrNo =
  9024.       MessageDlg(
  9025. {$IFDEF LINUX}
  9026.       sDeleteAxis2,
  9027. {$ENDIF}
  9028.         sDeleteAxis3 + pAxisToDelete.Title.Caption,
  9029.         mtWarning,
  9030.         [mbYes, mbNo],
  9031.         0));
  9032.   end;
  9033.  
  9034.   if (not Confirm) then
  9035.   begin
  9036. {remove this Y Axis from the ScreenObjectList:}
  9037.     ScreenObjectList.Delete(ScreenObjectList.IndexOf(pAxisToDelete));
  9038.     ScreenObjectList.Delete(ScreenObjectList.IndexOf(pAxisToDelete.Title));
  9039.     ScreenObjectList.Delete(ScreenObjectList.IndexOf(pAxisToDelete.Labels));
  9040.     //Dec(NoBasicScreenObjects, 3);
  9041. {remove this Y Axis from the AxisList:}
  9042.     FAxisList.Delete(Index);
  9043. {and remove it:}
  9044.     pAxisToDelete.Free;
  9045.     DoStyleChange(Self);
  9046.   end;
  9047. end;
  9048.  
  9049. {------------------------------------------------------------------------------
  9050.      Function: TCustomPlot.GetNoSeries
  9051.   Description: standard property Get function
  9052.        Author: Mat Ballard
  9053.  Date created: 25/25/2000
  9054. Date modified: 25/25/2000 by Mat Ballard
  9055.       Purpose: gets the number of Series
  9056.  Return Value: integer
  9057.  Known Issues:
  9058.  ------------------------------------------------------------------------------}
  9059. function TCustomPlot.GetNoSeries: Word;
  9060. begin
  9061.   GetNoSeries := FSeriesList.Count;
  9062. end;
  9063.  
  9064. {------------------------------------------------------------------------------
  9065.      Function: TCustomPlot.GetNoYAxes
  9066.   Description: standard property Get function
  9067.        Author: Mat Ballard
  9068.  Date created: 06/25/2000
  9069. Date modified: 06/25/2000 by Mat Ballard
  9070.       Purpose: gets the number of Y Axes
  9071.  Return Value: integer
  9072.  Known Issues:
  9073.  ------------------------------------------------------------------------------}
  9074. function TCustomPlot.GetNoYAxes: Integer;
  9075. begin
  9076.   GetNoYAxes := FAxisList.Count-1;
  9077. end;
  9078.  
  9079. {------------------------------------------------------------------------------
  9080.     Procedure: TCustomPlot.SetNoYAxes
  9081.   Description: standard property Set procedure
  9082.        Author: Mat Ballard
  9083.  Date created: 04/25/2000
  9084. Date modified: 04/25/2000 by Mat Ballard
  9085.       Purpose: sets the number of Y Axes
  9086.  Known Issues: it is a fairly brutal way of setting the number of Y Axes
  9087.  ------------------------------------------------------------------------------}
  9088. procedure TCustomPlot.SetNoYAxes(Value: Integer);
  9089. var
  9090.   i: Integer;
  9091. begin
  9092.   if (Value < 1) then exit;
  9093.  
  9094.   if (Value = FAxisList.Count-1) then exit;
  9095.  
  9096.   if (Value > 15) then raise
  9097.     EComponentError.CreateFmt(sSetNoYAxes1, [Value]);
  9098.  
  9099.   if (Value < FAxisList.Count-1) then
  9100.   begin
  9101. {we need to delete some axes:}
  9102.     for i := FAxisList.Count-1 downto Value+1 do
  9103.     begin
  9104.       DeleteAxis(i, FALSE);
  9105.     end;
  9106.   end
  9107.   else
  9108.   begin
  9109. {in order to avoid creating an extra axis when a 3D plot is loaded:}
  9110.     if not (csLoading in ComponentState) then
  9111. {add some axes:}
  9112.       for i := FAxisList.Count-1 to Value-1 do
  9113.       begin
  9114.         NewAxisClick(Self);
  9115.       end;
  9116.   end;
  9117. end;
  9118.  
  9119. {------------------------------------------------------------------------------
  9120.     Procedure: TCustomPlot.SetPlotType
  9121.   Description: standard property Set procedure
  9122.        Author: Mat Ballard
  9123.  Date created: 09/20/2000
  9124. Date modified: 01/16/2001 by Mat Ballard
  9125.       Purpose: sets the PlotType property
  9126.  Known Issues: under development
  9127.  ------------------------------------------------------------------------------}
  9128. procedure TCustomPlot.SetPlotType(Value: TPlotType);
  9129. var
  9130.   i: Integer;
  9131.   OldIgnoreChanges: Boolean;
  9132.  
  9133.   procedure AddZAxis;
  9134.   begin
  9135.     FZAxis := TAngleAxis.Create(Self);
  9136.     FZAxis.FireEvents := FALSE;
  9137.     FZAxis.Name := 'Z';
  9138.     {FZAxis.Left := FXAxis.Left;
  9139.     FZAxis.Top := FXAxis.MidY;}
  9140.     FZAxis.Length := FXAxis.Width div 3;
  9141.     FAxisList.Add(FZAxis);
  9142.     ScreenObjectList.Add(FZAxis);
  9143.     //Inc(NoBasicScreenObjects);
  9144.     FBorder.Left := Self.Width div 3;
  9145.     FBorder.BottomGap := Self.Height div 3;
  9146.     FZAxis.OnChange := DoStyleChange;
  9147.   end;
  9148.   
  9149.   procedure RemoveZAxis;
  9150.   begin
  9151.     FZAxis.OnChange := nil;
  9152.     FAxisList.Remove(FZAxis);
  9153.     ScreenObjectList.Remove(FZAxis);
  9154.     //Dec(NoBasicScreenObjects);
  9155.     FZAxis.Free;
  9156.     FZAxis := nil;
  9157.   end;
  9158.  
  9159. begin
  9160.   if (FPlotType = Value) then exit;
  9161.  
  9162.   OldIgnoreChanges := IgnoreChanges;
  9163.   IgnoreChanges := TRUE;
  9164.  
  9165.   if (FZAxis <> nil) then
  9166.     if (Value < pt3DContour) then
  9167.       RemoveZAxis;
  9168.  
  9169.   if (csDesigning in ComponentState) then
  9170.     NoSeries := 2;
  9171.  
  9172.   FPlotType := Value;
  9173.  
  9174. {clean up axes:}  
  9175.   for i := 0 to FAxisList.Count-1 do
  9176.   begin
  9177.     TAxis(FAxisList.Items[i]).FireEvents := FALSE;
  9178.     TAxis(FAxisList.Items[i]).Visible := TRUE;
  9179.   end;
  9180.   FYAxis.Title.Visible := TRUE;
  9181.   FXAxis.Title.Alignment := taCenter;
  9182.  
  9183. {clear previous Series pen settings:}
  9184.   for i := 0 to FSeriesList.Count-1 do
  9185.   begin
  9186.     Series[i].Pen.Width := 1;
  9187.     Series[i].Symbol := syNone;
  9188.   end;
  9189.  
  9190. {re-scale the primary X Axis:}
  9191.   if (FSeriesList.TotalNoPts > 0) then
  9192.   begin
  9193.     if (FSeriesList.Xmin >= 0) then
  9194.       XAxis.Min := 0
  9195.     else
  9196.       XAxis.Min := Round(FSeriesList.Xmin - 0.999);
  9197.     XAxis.Max := Round(FSeriesList.Xmax + 0.999);
  9198.   end;
  9199.  
  9200. {re-scale the primary Y Axis:}
  9201.   if (FSeriesList.TotalNoPts > 0) then
  9202.   begin
  9203.     if (FSeriesList.Ymin >= 0) then
  9204.       YAxis.Min := 0
  9205.     else
  9206.       YAxis.Min := Round(FSeriesList.Ymin - 0.999);
  9207.     YAxis.Max := Round(FSeriesList.Ymax + 0.999);
  9208.   end;
  9209.  
  9210.   FLegend.Visible := TRUE;
  9211.  
  9212.   case FPlotType of
  9213.     ptXY: ;
  9214.  
  9215.     ptError:
  9216.       begin
  9217.         {if (csDesigning in ComponentState) then
  9218.           MakeDummyData(20);}
  9219.         i := 0;
  9220.         while (i <= FSeriesList.Count-2) do
  9221.         begin
  9222.           Series[i].Symbol := TSymbol(1 + (i div 2) mod (Ord(High(TSymbol))-2));
  9223.           Inc(i, 2);
  9224.         end;
  9225.         if (FSeriesList.TotalNoPts > 0) then
  9226.         begin
  9227.           YAxis.Min := Round(FSeriesList.YErrorMin - 0.999);
  9228.           YAxis.Max := Round(FSeriesList.YErrorMax + 0.999);
  9229.         end;
  9230.       end;
  9231.  
  9232.     ptMultiple:
  9233.       begin
  9234.         for i := 0 to FSeriesList.Count-1 do
  9235.         begin
  9236.           Series[i].Pen.Width := 0;
  9237.           Series[i].Symbol := TSymbol(1 + i mod (Ord(High(TSymbol))-2));
  9238.         end;
  9239.       end;
  9240.  
  9241.     ptColumn: YAxis.Min := 0;
  9242.  
  9243.     ptStack:
  9244.       begin
  9245.         YAxis.Min := 0;
  9246.         if (FSeriesList.TotalNoPts > 0) then
  9247.           YAxis.Max := Round(FSeriesList.Count * FSeriesList.Ymax + 0.999);
  9248.       end;
  9249.  
  9250.     ptNormStack:
  9251.       begin
  9252.         YAxis.Min := 0;
  9253.         YAxis.Max := 100;
  9254.       end;
  9255.  
  9256.     ptPie:
  9257.       begin
  9258.         for i := 0 to FAxisList.Count-1 do
  9259.           TAxis(FAxisList.Items[i]).Visible := FALSE;
  9260.       end;
  9261.  
  9262.     ptPolar:
  9263.       begin
  9264.         if (FXAxis.Min > -FXAxis.Max) then
  9265.           FXAxis.Min := -FXAxis.Max;
  9266.         if (FXAxis.Max < -FXAxis.Min) then
  9267.           FXAxis.Max := -FXAxis.Min;
  9268.         if (FYAxis.Min > -FYAxis.Max) then
  9269.           FYAxis.Min := -FYAxis.Max;
  9270.         if (FYAxis.Max < -FYAxis.Min) then
  9271.           FYAxis.Max := -FYAxis.Min;
  9272.         FXAxis.Intercept := 0;
  9273.         FYAxis.Intercept := 0;
  9274.         FYAxis.Title.Visible := FALSE;
  9275.         FXAxis.Title.Alignment := taRightJustify;
  9276.       end;
  9277.  
  9278.     ptContour:
  9279.       begin
  9280.         if (csDesigning in ComponentState) then
  9281.         begin
  9282.           NoSeries := 10;
  9283.           MakeDummyData(20);
  9284.         end;
  9285.         FLegend.Visible := FALSE;
  9286.       end;
  9287.  
  9288.     pt3DContour, pt3DWire{, pt3DSurface}:
  9289.       begin
  9290.         if (FZAxis = nil) then
  9291.           AddZAxis;
  9292.         if (csDesigning in ComponentState) then
  9293.         begin
  9294.           FBorder.Left := 3 * FBorder.Left div 2;
  9295.           FBorder.BottomGap := 3 * FBorder.BottomGap div 2; 
  9296.           NoSeries := 10;
  9297.           MakeDummyData(20);
  9298.         end;
  9299.         FLegend.Visible := FALSE;
  9300.       end;
  9301.   end;
  9302.  
  9303. {deal with axes:}
  9304.   SetAxisDimensions;
  9305.   for i := 0 to FAxisList.Count-1 do
  9306.   begin
  9307.     TAxis(FAxisList.Items[i]).Intercept := 0;
  9308.     TAxis(FAxisList.Items[i]).FireEvents := TRUE;
  9309.   end;
  9310.  
  9311.   SetDefaults;
  9312.   IgnoreChanges := OldIgnoreChanges;
  9313.  
  9314.   DoStyleChange(Self);
  9315. end;
  9316.  
  9317. {------------------------------------------------------------------------------
  9318.     Procedure: TCustomPlot.SetPolarRange
  9319.   Description: standard property Set procedure
  9320.        Author: Mat Ballard
  9321.  Date created: 09/20/2000
  9322. Date modified: 01/16/2001 by Mat Ballard
  9323.       Purpose: sets the PolarRange property
  9324.  Known Issues: under development
  9325.  ------------------------------------------------------------------------------}
  9326. procedure TCustomPlot.SetPolarRange(Value: Single);
  9327. begin
  9328.   if (FPolarRange = Value) then exit;
  9329.  
  9330.   FPolarRange := Value;
  9331.   DoStyleChange(Self);
  9332. end;
  9333.  
  9334. {------------------------------------------------------------------------------
  9335.     Procedure: TCustomPlot.SetPopupOptions
  9336.   Description: standard property Set procedure
  9337.        Author: Mat Ballard
  9338.  Date created: 09/25/2000
  9339. Date modified: 09/25/2000 by Mat Ballard
  9340.       Purpose: sets the PopupOptions property, and informs any TPlotMenu and
  9341.                TPlotToolBar of the change
  9342.  Known Issues:
  9343.  ------------------------------------------------------------------------------}
  9344. procedure TCustomPlot.SetPopupOptions(Value: TPopupOptions);
  9345. begin
  9346.   FPopupOptions.Assign(Value);
  9347.   if (Self.FPlotMenu <> nil) then
  9348.     TPlotMenu(FPlotMenu).ApplyOptions(Value);
  9349.   if (Self.FPlotToolBar <> nil) then
  9350.     TPlotToolBar(FPlotToolBar).ApplyOptions(Value);
  9351. end;
  9352.  
  9353. {------------------------------------------------------------------------------
  9354.     Procedure: TCustomPlot.SetPlotMenu
  9355.   Description: standard property Set procedure
  9356.        Author: Mat Ballard
  9357.  Date created: 09/25/2000
  9358. Date modified: 09/25/2000 by Mat Ballard
  9359.       Purpose: sets the PlotMenu property
  9360.  Known Issues:
  9361.  ------------------------------------------------------------------------------}
  9362. procedure TCustomPlot.SetPlotMenu(Value: TMainMenu);
  9363. begin
  9364.   FPlotMenu := Value;
  9365.   if (FPlotMenu <> nil) then
  9366.     TPlotMenu(FPlotMenu).ApplyOptions(FPopupOptions);
  9367. end;
  9368.  
  9369. {------------------------------------------------------------------------------
  9370.     Procedure: TCustomPlot.SetPlotToolBar
  9371.   Description: standard property Set procedure
  9372.        Author: Mat Ballard
  9373.  Date created: 09/25/2000
  9374. Date modified: 04/25/2001 by Mat Ballard
  9375.       Purpose: sets the PlotToolBar property
  9376.  Known Issues:
  9377.  ------------------------------------------------------------------------------}
  9378. procedure TCustomPlot.SetPlotToolBar(Value: TToolBar);
  9379. begin
  9380.   FPlotToolBar := Value;
  9381.   if (FPlotToolBar <> nil) then
  9382.     TPlotToolBar(FPlotToolBar).ApplyOptions(FPopupOptions);
  9383. end;
  9384.  
  9385. {------------------------------------------------------------------------------
  9386.     Procedure: TCustomPlot.SetPlotActionList
  9387.   Description: standard property Set procedure
  9388.        Author: Mat Ballard
  9389.  Date created: 09/25/2000
  9390. Date modified: 09/25/2000 by Mat Ballard
  9391.       Purpose: sets the PlotActionList property
  9392.  Known Issues:
  9393.  ------------------------------------------------------------------------------}
  9394. {$IFDEF DELPHI4_UP}
  9395. {procedure TCustomPlot.SetPlotActionList(Value: TActionList);
  9396. begin
  9397.   FPlotActionList := Value;
  9398. end;}
  9399. {$ENDIF}
  9400.  
  9401. {------------------------------------------------------------------------------
  9402.     Procedure: TCustomPlot.Clear
  9403.   Description: Saves any changed files (at user request) and then clears the SeriesList.
  9404.        Author: Mat Ballard
  9405.  Date created: 04/25/2000
  9406. Date modified: 04/25/2000 by Mat Ballard
  9407.       Purpose: Series management: wraps TSeriesList.ClearSeries
  9408.  Known Issues: it is a fairly brutal way of setting the number of Y Axes
  9409.  ------------------------------------------------------------------------------}
  9410. procedure TCustomPlot.Clear(Cancellable: Boolean);
  9411. var
  9412.   TheResult: Integer;
  9413.   TheMessage: String;
  9414. {$IFDEF MSWINDOWS}
  9415.   pMessage: array[0..255] of Char;
  9416. {$ENDIF}
  9417. begin
  9418.   if (csDesigning in ComponentState) then exit;
  9419.  
  9420.   if (FSeriesList.Count > 0) then
  9421.   begin
  9422.     if (FSeriesList.DataChanged) then
  9423.     begin
  9424.       if (Length(FFileName) > 0) then
  9425.         TheMessage := ExtractFileName(FFileName)
  9426.        else
  9427.         TheMessage := sThisFile;
  9428.        TheMessage := sSave + TheMessage + sBeforeClose;
  9429. {NB: MessageDlg provokes an access violation because the Window may have gone:}
  9430. {$IFDEF MSWINDOWS}
  9431.       StrPCopy(pMessage, TheMessage);
  9432.       if (Cancellable) then
  9433.         TheResult := {Windows.}MessageBox(0, pMessage, pChar(sFileHasChanged), MB_YESNOCANCEL + MB_ICONQUESTION)
  9434.        else
  9435.         TheResult := {Windows.}MessageBox(0, pMessage, pChar(sFileHasChanged), MB_YESNO + MB_ICONQUESTION);
  9436. {$ENDIF}
  9437. {$IFDEF LINUX}
  9438.       if (Cancellable) then
  9439.         TheResult := MessageDlg(sSaveFile,
  9440.           TheMessage,
  9441.           mtWarning,
  9442.           [mbYes, mbNo, mbCancel],
  9443.           0)
  9444.        else
  9445.         TheResult := MessageDlg(sSaveFile,
  9446.           TheMessage,
  9447.           mtWarning,
  9448.           [mbYes, mbNo],
  9449.           0);
  9450. {$ENDIF}
  9451.       case TheResult of
  9452.         mrYes: SaveClick(Self);
  9453.         mrNo: ;
  9454.         mrCancel: Exit;
  9455.       end;
  9456.     end;
  9457.  
  9458.     FSeriesList.ClearSeries;
  9459.     if ((FPlotMenu <> nil) and (Length(FFileName) > 0)) then
  9460.       TPlotMenu(FPlotMenu).AddHistory(FFileName);
  9461.     DoFileClose(FFileName);
  9462.   end;
  9463.   FFileName := '';
  9464. end;
  9465.  
  9466. {------------------------------------------------------------------------------
  9467.     Procedure: TCustomPlot.DoStyleChange
  9468.   Description: informs the user of a change in the plot that requires a repaint
  9469.        Author: Mat Ballard
  9470.  Date created: 02/20/2001
  9471. Date modified: 02/20/2001 by Mat Ballard
  9472.       Purpose: Fires the OnStyleChange event
  9473.  Known Issues:
  9474.  ------------------------------------------------------------------------------}
  9475. procedure TCustomPlot.DoStyleChange(Sender: TObject);
  9476. begin
  9477.   if (IgnoreChanges) then exit;
  9478.  
  9479.   SetAxisDimensions;
  9480.  
  9481.   if assigned(FOnStyleChange) then OnStyleChange(Sender);
  9482.   Refresh;
  9483. end;
  9484.  
  9485. {------------------------------------------------------------------------------
  9486.     Procedure: TCustomPlot.DoDataChange
  9487.   Description: informs the user of a change in the data of the plot that requires a repaint
  9488.        Author: Mat Ballard
  9489.  Date created: 03/07/2001
  9490. Date modified: 03/07/2001 by Mat Ballard
  9491.       Purpose: Fires the OnDataChange event
  9492.  Known Issues:
  9493.  ------------------------------------------------------------------------------}
  9494. procedure TCustomPlot.DoDataChange(Sender: TObject);
  9495. begin
  9496.   if (IgnoreChanges) then exit;
  9497.  
  9498.   if assigned(FOnDataChange) then OnDataChange(Sender);
  9499.   Refresh;
  9500. end;
  9501.  
  9502. {------------------------------------------------------------------------------
  9503.     Procedure: TCustomPlot.DoFileClose
  9504.   Description: informs the user of a file close
  9505.        Author: Mat Ballard
  9506.  Date created: 09/07/2000
  9507. Date modified: 09/07/2000 by Mat Ballard
  9508.       Purpose: Fires the OnFileClose event
  9509.  Known Issues:
  9510.  ------------------------------------------------------------------------------}
  9511. procedure TCustomPlot.DoFileClose(AFileName: String);
  9512. begin
  9513.   if assigned(FOnFileClose) then
  9514.     OnFileClose(Self, AFileName);
  9515. end;
  9516.  
  9517. {------------------------------------------------------------------------------
  9518.      Function: TCustomPlot.GetZAngle
  9519.   Description: standard property getting method
  9520.        Author: Mat Ballard
  9521.  Date created: 01/07/2001
  9522. Date modified: 01/07/2001 by Mat Ballard
  9523.       Purpose: gets the angle of the Z Axis, if any
  9524.  Known Issues:
  9525.  ------------------------------------------------------------------------------}
  9526. function TCustomPlot.GetZAngle: Word;
  9527. begin
  9528.   if (FZAxis <> nil) then
  9529.     GetZAngle := FZAxis.Angle
  9530.    else
  9531.     GetZAngle := 225;
  9532. end;
  9533.  
  9534. {------------------------------------------------------------------------------
  9535.      Function: TCustomPlot.GetZLength
  9536.   Description: standard property getting method
  9537.        Author: Mat Ballard
  9538.  Date created: 01/07/2001
  9539. Date modified: 01/07/2001 by Mat Ballard
  9540.       Purpose: gets the Length of the Z Axis, if any
  9541.  Known Issues:
  9542.  ------------------------------------------------------------------------------}
  9543. function TCustomPlot.GetZLength: Word;
  9544. begin
  9545.   if (FZAxis <> nil) then
  9546.     GetZLength := FZAxis.Length
  9547.    else
  9548.     GetZLength := 100;
  9549. end;
  9550.  
  9551. {------------------------------------------------------------------------------
  9552.     Procedure: TCustomPlot.SetZAngle
  9553.   Description: standard property setting method
  9554.        Author: Mat Ballard
  9555.  Date created: 01/07/2001
  9556. Date modified: 01/07/2001 by Mat Ballard
  9557.       Purpose: sets the angle of the Z Axis, if any
  9558.  Known Issues:
  9559.  ------------------------------------------------------------------------------}
  9560. procedure TCustomPlot.SetZAngle(Value: Word);
  9561. begin
  9562.   if (FZAxis <> nil) then
  9563.     if (Value <> FZAxis.Angle) then
  9564.       FZAxis.Angle := Value;
  9565. end;
  9566.  
  9567. {------------------------------------------------------------------------------
  9568.     Procedure: TCustomPlot.SetZLength
  9569.   Description: standard property setting method
  9570.        Author: Mat Ballard
  9571.  Date created: 01/07/2001
  9572. Date modified: 01/07/2001 by Mat Ballard
  9573.       Purpose: sets the Length of the Z Axis, if any
  9574.  Known Issues:
  9575.  ------------------------------------------------------------------------------}
  9576. procedure TCustomPlot.SetZLength(Value: Word);
  9577. begin
  9578.   if (FZAxis <> nil) then
  9579.     if (Value <> FZAxis.Length) then
  9580.       FZAxis.Length := Value;
  9581. end;
  9582.  
  9583. {------------------------------------------------------------------------------
  9584.     Procedure: TCustomPlot.SetZLink
  9585.   Description: standard property setting method
  9586.        Author: Mat Ballard
  9587.  Date created: 01/07/2001
  9588. Date modified: 01/07/2001 by Mat Ballard
  9589.       Purpose: sets the Link property - that is, should we link 3D series ?
  9590.  Known Issues:
  9591.  ------------------------------------------------------------------------------}
  9592. procedure TCustomPlot.SetZLink(Value: Boolean);
  9593. begin
  9594.   if (Value <> FZLink) then
  9595.     FZLink := Value;
  9596.   DoStyleChange(Self);
  9597. end;
  9598.  
  9599.  
  9600. {------------------------------------------------------------------------------
  9601.     Procedure: TCustomPlot.SetXYFastAt
  9602.   Description: standard property setting method
  9603.        Author: Mat Ballard
  9604.  Date created: 05/07/2001
  9605. Date modified: 05/07/2001 by Mat Ballard
  9606.       Purpose: sets the Bridge point of the data - when it switches to the
  9607.                hyperfast draw algorithm
  9608.  Known Issues:
  9609.  ------------------------------------------------------------------------------}
  9610. procedure TCustomPlot.SetXYFastAt(Value: Longint);
  9611. begin
  9612.   if (Value > 100) then
  9613.     FXYFastAt := Value;
  9614.   DoStyleChange(Self);
  9615. end;
  9616.  
  9617.  
  9618. end.
  9619.  
  9620.  
  9621.  
  9622.