home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kompon / d123456 / CHEMPLOT.ZIP / TPlot / Plot.pas < prev    next >
Pascal/Delphi Source File  |  2001-07-31  |  367KB  |  10,249 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.     Thanks (or blame) to:
  57.         http://www.freetranslation.com/
  58.         for the French, German, Italian, Norwegian, Portuguese and Spanish translations.
  59.     Thanks to Amy Khai Luong <akluong@sandia.gov> for help in pointers and solutions to D6 compatibility.
  60.     Thanks to Rakesh Nagarajan <rakesh@pathbox.wustl.edu> for help in pointers and solutions to BCB5 compatibility.
  61.  
  62. Last Modified: 29/07/2001
  63. Current Version: 2.32
  64.  
  65. You may retrieve the latest version of this file from:
  66.  
  67.         http://Chemware.hypermart.net/
  68.  
  69. This work was created with the Project JEDI VCL guidelines:
  70.  
  71.         http://www.delphi-jedi.org/Jedi:VCLVCL
  72.  
  73. in mind.
  74.  
  75. Kylix issues:
  76.     - Yes, there is no printing (yet)
  77.     - Yes, there is no GIF support (yet)
  78.     - Note the peculiar work-arounds that apply to resources:
  79.       you have to patch QGraphics see ResourceFix.pas, or FreeClx on SourceForge.
  80.     - No, everything else works.
  81.     - Help does not work yet - but check out:
  82.       http://Chemware.hypermart.net/tplot/help/ to see where we are heading
  83.  
  84. Kylix tricks and traps:
  85.     - symlinks: put Symlinks from your home directory to your
  86.       development and kylix directories:
  87.       >cd ~
  88.       >ln -s /opt/kylix
  89.       >ln -s /opt/kylix/help kylixhelp
  90.       >ln -s /mnt/dos/delphi/components/tplot
  91.     - case sensitivity - filenames, resources, unit names, etc, etc, etc.
  92.     - permissions: suggest you make $(KYLIX)/bin user-writable, and put final binaries there
  93.     - put XKill on the taskbar - you'll need it !
  94.     - from the command line: "ps -A", then "kill nnn"
  95.     - CLX objects and classes don't correspond 100% to VCL ones:
  96.       there are some old properties and methods missing, and some new ones
  97.     - eg: QForms.TForm is different from Forms.TForm.
  98.       This means you can open a form saved from Delphi into Linux, and vice-versa,
  99.       _BUT_ you will get errors about non-existent properties. eg:
  100.           Delphi bitches about:
  101.             BorderStyle,
  102.             HelpType,
  103.             Color (different clXXXs),
  104.             Font.Weight
  105.           Kylix bitches about:
  106.             BorderStyle,
  107.       If you don't save a form from the current IDE, then it will hopefully compile
  108.       (and run) OK, BUT you may get exceptions when you open a dialog.
  109.  
  110. Known Issues:
  111.     - D1 and D2 are no longer supported. The chosen localization technique (resourcestring)
  112.       is not supported under D1 and D2.
  113.     - Printing does not (yet) work under Kylix.
  114.     - TToolBar DOES NOT WORK if it Plot property is set in the IDE !
  115.       Please set its plot property in code ! (See Normal1.pas)
  116.       Also, you cannot select individual buttons until AFTER you have
  117.       "View as Text" then "View As Form".
  118.     - $IFDEFs: TPlot _WAS_ used in a Delphi 1 application, and will be migrated
  119.       to Linux. $IFDEFs are therefore unavoidable.
  120.     - Explicit dereferencing (eg: XData^[i]) _IS_ required for compatibility
  121.       with Delphi 1. Besides, I prefer it to distinguish dynamic from static arrays.
  122.     - Since TPlotMenu, etc are useless without TPlot, there is only the one
  123.       registration unit: TPlot_Reg.pas.
  124.     - if you work across different versions of Delphi, ALWAYS save any form from
  125.       the lowest version of Delphi (eg: Delphi 1), because otherwise the DFM
  126.       files will contain extra properties that will cause stream read errors in
  127.       lower versions of Delphi.
  128.  
  129. Comparison to TChart version 4 (in Delphi 5):
  130.     - Compare Normal.exe to TChartNormal.exe with "Fastline", then "Line" for symbols :
  131. 10 July 2001.
  132. Number of Points         TPlot           TChart
  133.                        fps      K      fps      K
  134. Winnt 4, sp5, no IDE:
  135.     101                28.9    2836    13.2    2108
  136.   9,997                 6.61   2956     2.67   2628
  137.  10,001                19.8    2948     2.56   2644
  138.  99,889                 7.71   3688     0.38   6084
  139. 992,403                 1.42  10588     0.05  41088
  140. With square Symbols, "Line":
  141.     101                28.9    2960    12.4    2120
  142.  99,889                 to be fixed     0.15   6096
  143. No TPlotImageList, TPlotMenu, TPlotToolBar:
  144.     101                39.0    2572
  145.  
  146.                                 All - Shared = Total
  147. Mandrake 7.2 std, no IDE):
  148.     101                10.3    8216 - 5808 = 2408
  149.  99,889                 6.90    9000 - 5832 = 3168
  150. 992,403                 1.53   15988 - 5844 = 10144
  151. Mandrake 7.2 std under Kylix IDE:
  152.     101                 10.3    8220 - 5784 = 2436
  153.  99,889                 6.10    9004 - 5808 = 3196
  154. 992,403                 1.52   15992 - 5820 = 10172
  155. No TPlotImageList, TPlotMenu, TPlotToolBar:
  156.     101                12.15    7620 - 5572 = 2028
  157.  
  158. Comments:
  159.  1. TPlot is 3 - 20 x faster than TChart.
  160.  2. The TPlot demo also has the TPlotToolBar, which the TChart demo does not.
  161.     Resizing and redrawing this also adds to the TPlot times.
  162.  3. It uses more memory (700K) with a small number of points, mainly due to
  163.     TPlotMenu, TPlotImageList, and TPlotToolBar.
  164.     It uses much less memory (75% less !) with a large number of points.
  165.  4. Although not directly visible in these numbers, large series are built
  166.     much more quickly under Linux => memory management is more efficient.
  167.     This is also seen in the superior times of large data sets.
  168.  
  169.  
  170. Feature Comparison:
  171.                       TPlot            TChart
  172.     Data file IO       yes               no
  173.     Extensible file IO yes               no
  174.     Click & drag       yes               no
  175.       objects
  176.     Popup menu         yes               no
  177.     Main menu          yes               no
  178.     Toolbar            yes               no
  179.     Context sensitive  yes               no
  180.     Web images         yes               only GIF in Pro version
  181.     Web pages          yes               no
  182.     Sticky notes       yes               no
  183.     Dynamic,           yes               no
  184.       movable axes
  185.     Math functions:
  186.       User defined     yes               no
  187.       Average          yes              yes
  188.       Compression      yes               no
  189.       Contraction      yes               no
  190.       Differentiation  yes               no
  191.       Integration      yes               no
  192.       Linear Fits      yes               no
  193.       Moving Average   yes               no
  194.       Nearest Point    yes               no
  195.       Position         yes               no
  196.       Smoothing        yes               no
  197.       Splines          yes               no
  198.     True 3D plots      yes               Pro version
  199.     Database support   in development    yes
  200.  
  201. TO BE DONE:
  202.     - Right click on legend ? Edit Series ?
  203.     - Fix severe TPlotToolBar problem:
  204.       works fine when created dynamically, but dies in constructor with
  205.       "Component not found: TToolButton" when run from IDE placement.
  206.     - debug and thoroughly test TDBPlot
  207.     - get the HTML Help system working under Linux
  208.     
  209. Future Development:
  210.     - Printing under Kylix.
  211.     - streaming of component properties sometimes does not work
  212.       eg: try setting Axis widths to different values
  213.     - implementation of GIFs under Linux:
  214.     - addition of a "Financial" menu, similar to "File", "Edit", etc, and
  215.       populate it with goodies like RSI.
  216.     - re-write the "DetermineMenuVisibility and ...Enabledness so that they can
  217.       control the visibility of buttons in TPlotToolBar.
  218.     - Marry Parser10 to a good minimization algorithm (eg: Simplex) so that users
  219.       can fit _ANY_ function.
  220.     - add some keyboard input ? not straightforward
  221.     - rationalization and rotation of 3D axes
  222.     - 0 deg to 360 deg on Polars ?
  223.     - ptGantt ?
  224.     - drag points ?
  225.     - OpenGL 3D surfaces ?
  226.     - add Polynomial fits (CurveFit.pas).
  227.     - move "Result" of fits from TPlot to TSeries -> each series can have its own fit
  228.  
  229. History:
  230.  2.32  26 Jul 2001: Change most "with xxx do" blocks to "xxx."
  231.                     Fixed "Canvas.Start" bug in GetDrawing under Linux, but printing still doesn't work.
  232.                     Remove the 3rd party components from the Packages.
  233.                     This causes warnings, but this is better than the "Missing file" errors.
  234.                     They can be added back in by the user.
  235.  2.31  25 Jul 2001: Added GetPlotTypeAsString, fixed TPlotToolBar order bug in BCB.
  236.  2.30  23 Jul 2001: Modified AxisEditor and SeriesEditor to handle these new properties.
  237.  2.29  22 Jul 2001: Added Limits (Upper, Lower and Visible) to Axes and
  238.                     ShadeLimits and DrawShades to Series (these are complementary).
  239.  2.28  18 Jul 2001: Add financial menu items, and skeleton functions.
  240.  2.27  18 Jul 2001: Put $I Plot.inc and $IFDEFs into Plot200_R50.dpk to fix "File not found" issues with 3rd party components.
  241.                     Seems to work. Will extend to the D4 and Kylix versions.
  242.  2.26  17 Jul 2001: Completely rewrite Draw3DContour: implement High detail plots.
  243.                     Add ContourWireFrame property.
  244.  2.25  17 Jul 2001: Implement DrawLineContour.
  245.                     Add ContourStart and ContourInterval properties.
  246.                     Modify Properties dialog to include these two new properties.
  247.  2.24  16 Jul 2001: Completely rewrite DrawContour to make it simpler, quicker, less fragile,
  248.                     more compatible with the other 3D methods, especially future OpenGl extensions.
  249.  2.23  12 Jul 2001: Added Properties Property and PropertyEditor.
  250.  2.22   6 Jul 2001: Translations finished. Resize all labels and forms, debug.
  251.                     Originals are in TPlot.xls, thence the "lang" subdirectory.
  252.                     NB: these are machine translations, and so are probably very
  253.                     humorous and misleading ! 
  254.  2.21   3 Jul 2001: Perform translations !
  255.  2.20   2 Jul 2001: Move all ResourceStrings into files for translation,
  256.                     and load according to the Language defines in Misc.pas.
  257.  2.19   1 Jul 2001: place _ALL_ string resources into ResourceString statements.
  258.  2.18  30 Jun 2001: rewrite TPlot.CreateMenus to use new ResourceString instead of
  259.                     the old Strlst32.res resource file.
  260.  2.17  26 Jun 2001: Place Plot menu and Caption resources into resourcestring ->
  261.                     no longer need StrLst32.res, or resource editor.
  262.  2.16  16 Jun 2001: Make Selection: TAngleRect. This allows:
  263.                     Selection, Clicking and dragging of the Z Axis.
  264.                     Work over drawing Walls and Grids.
  265.                     Work over SetAxisDimensions.
  266.  2.15  14 Jun 2001: Work over the TAxis.Draw method to eliminate bugs in click-and-drag selection (FLabels).
  267.  2.14  12 Jun 2001: Add GridColor and WallColor properties, and user interfaces thereto.
  268.  2.13   9 Jun 2001: Create TAngleRect - this will replace TRectangle as the ancestor
  269.                     for many sub-components: eg: TAxis.
  270.                     Reason: this will make ZAxes and titles clickable.
  271.  2.12   6 Jun 2001: DrawWalls for better 3D rendition.
  272.                     Fixed minor TickDirection bug in TAxisEditorForm.
  273.                     Fixed minor bug in rendition of labels on X Axis (Up not done properly).
  274.  2.11   5 Jun 2001: Much behind-the-scenes work on Linux:
  275.                     printing, jumping to web pages, mailing, and helping.
  276.                     Pity none of it works yet.
  277.  2.10   2 Jun 2001: Created 3DColumn plot type, implemented its TSeriesList.Draw method,
  278.                     modified TPlotPropertyEditorForm to manage it.
  279.                     Added ZLength property to TPlotPropertyEditorForm.
  280.  2.09  30 May 2001: Created Right Click and Drag popup menu - our first "gesture".
  281.                     Revised handling of its menuitems OnClick events and MouseUp methods. 
  282.                     Added TDBPlot to BCB project - but something is wrong !
  283.  2.08  29 May 2001: renamed Zoom.pas to PlotZoom.pas to avoid namespace clash with RALib !!!
  284.                     Fixed scaling bugs with 3D and Bubble plots.
  285.                     Added Linearize and Zero functions.
  286.  2.07  16 May 2001: renamed ToolEdit.pas to Plottooledit.pas to avoid namespace clash with RXLib
  287.                     Reworked autoscaling of axes.
  288.                     Fixed some TDBPlot issues (FReadOnly replaced by FDataLink.ReadOnly),
  289.                     but still not happy with it.
  290.  2.06  16 May 2001: Made many changes to graphics handling.
  291.                     There are now Bitmap, Drawing, GIF and Png properties.
  292.                     Saving or copying these now becomes a one-liner.
  293.                     Great for all those web developers out there.
  294.                     Massive amount of work on the help file to bring it up to date.
  295.                     Create ActiveX control.
  296.  2.05  16 May 2001: Changed from Jack Goman's pngunit to Eric Engler's Pngimage
  297.                     to enable a Png property under Windows.
  298.  2.04  16 May 2001: Made Draw public
  299.  2.03  16 May 2001: Add Drawing property
  300.  2.02  11 May 2001: Add Png property
  301.  2.01  11 May 2001: Get SaveAsPNG working under Kylix with Jon Shemitz's help.
  302.  2.00  10 May 2001: Bump up version number and release.
  303.  1.81   9 May 2001: Added TDBPlot projects to Kylix project group
  304.  1.80   8 May 2001: Added XYFastAt property
  305.  1.79   7 May 2001: Modified TSeries.Draw to use a different algorithm if
  306.                     NoPts > 10000.
  307.  1.78   6 May 2001: Rewrote loading of binary files to handle XText data.
  308.  1.77   5 May 2001: Fixed bugs in reading of XText data from text files.
  309.  1.76   4 May 2001: Fixed bugs in display of XText data in Axis.
  310.  1.75   3 May 2001: Modified TCustomPlot.SetPlotMenu and TCustomPlot.SetPlotToolBar
  311.                     to correctly apply the Popupoptions to TPlotMenu and TPlotToolBar;
  312.                     also fixed bugs in the ApplyOptions methods of those two components.
  313.  1.74   2 May 2001: Added "ApplyOptions" to TPlotMenu.
  314.  1.73   2 May 2001: Added the CanConfigure property to TPlotToolBar
  315.  1.72   2 May 2001: Removed TPlotToolBar property editor -
  316.                     Visibility of buttons now set by TPlot.PopupOptions.
  317.  1.71   1 May 2001: Fixed numerous features/bugs in TPlotToolBar under Kylix,
  318.                     eg: "Buttons" vs "Controls", different indexing.
  319.  1.70  30 Apr 2001: Re-worked file and stream loading and saving,
  320.                     moving most of it into TSeriesList. 
  321.  1.69  29 Apr 2001: added PageButtons in Zoomed mode.
  322.  1.68  26 Apr 2001: Re-build BCB3 projects, and fix buglets associated with BCB compatibility:
  323.                     TPlotToolBar in particular.
  324.  1.67  26 Apr 2001: Change EditPoint to be D1 compatible.
  325.  1.66  25 Apr 2001: Re-work Parser, ParseData and ConvertTextData to handle
  326.                     matrix of Z values (Eugene Parsons).
  327.  1.65  25 Apr 2001: Total re-write of TSeries.DrawPie. Ain't it pretty now ?
  328.  1.64  25 Apr 2001: Modify ContourDetail to add cdVHigh, then bump all up by one,
  329.                     then make cdLow rectangles, cdMedium triangles, cdHigh points, cdVHigh filled.
  330.  1.63  22 Apr 2001: Added ZLength property, other fixes.
  331.  1.62  19 Apr 2001: Finally got TPlotToolBar working properly !
  332.  1.61  19 Apr 2001: Enabled multiline Title.Captions.
  333.  1.60  19 Apr 2001: Fixed Columnses visibility buglet.
  334.  1.59  19 Apr 2001: Moved Legend drawing code into TLegend, and added check marks.
  335.  1.58  19 Apr 2001: Implemented the lfSI format for output (M, K, etc)
  336.  1.57  19 Apr 2001: Fixed fiendish little bug that causes repeated redraw of plots on file opening.
  337.  1.56  18 Apr 2001: Added XTEXT support to text file IO; Problem: Binary file IO ?
  338.  1.55  18 Apr 2001: Added MultiJoin property to better manage High-Low-open-Close plots.
  339.  1.54  18 Apr 2001: Augmented the Import Parser to cope with XYZ triple text files.
  340.  1.53  16 Apr 2001: Fixed bugs in DataEditor.
  341.  1.52  16 Apr 2001: Fixed "ZoomOutClick" bugs.
  342.  1.51  16 Apr 2001: Implemented "NewSeriesClick".
  343.  1.50  11 Apr 2001: Added ptBubble PlotType, and all associated methods and variables.
  344.  1.49   9 Apr 2001: Fixed/upgraded Parser, ConvertTextData and ParseData to import
  345.                     3D data.
  346.  1.48   4 Apr 2001: Implemented Functions using TParser10- eat your heart out David B !
  347.  1.47   3 Apr 2001: Routed all dialog geometries into Misc.SetDialogGeometry()
  348.  1.46   2 Apr 2001: ... then fixed Linux color bug in the text output on Pie graphs
  349.  1.45   1 Apr 2001: Finally nailed correct positioning of the text output on Pie graphs
  350.  1.44  29 Mar 2001: Much work fixing Linux bugs: LoadStr for string resources (menus),
  351.                     loading bitmaps (many thanks to Stephan Hoffmeister), TCanvas.Pie, etc.  
  352.  1.43  28 Mar 2001: Major overhaul of dialogs: add "Apply" button and code to most.
  353.  1.42  27 Mar 2001: Get property editors to compile. "About" works once, but then
  354.                     Kylix freezes whenever TPlot is installed.
  355.  1.41  27 Mar 2001: Fix Polygon issue, somehow. And other Kylix buglets.
  356.  1.40  23 Mar 2001: Kylix finally arrives. Fix many issues, but not all. See "Traps" below.
  357.  1.39  15 Mar 2001: Changed licensing from MPL to QPL.
  358.                     In practise, this only affects commercial developers.
  359.  1.38  15 Mar 2001: Added TPlotComponentEditor to Plot_reg.pas to give design-time menus.
  360.  1.37  15 Mar 2001: Revise TSeries.DrawPie to add labels.
  361.  1.36  14 Mar 2001: Revise TSeries.XStringData extensively.
  362.  1.35  12 Mar 2001: Surface many TSeriesList methods in TPlot for TDBPlot to override.
  363.  1.34   7 Mar 2001: Revise the OnStyleChange/OnDataChange events in TSeries and TSeriesList
  364.  1.33   2 Mar 2001: Begin work on TDBPlot.
  365.  1.32   2 Mar 2001: We have a renaming frenzy, to make the purpose of the major
  366.                     series manipulation functions more obvious.
  367.                       Add         -> AddSeries
  368.                       AddExternal -> AddExternalSeries
  369.                       AddInternal -> AddInternalSeries
  370.                       AddSlice    -> AddData
  371.                     My apologies to all existing users. This will break existing
  372.                     code, but fixing it should be trivial.
  373.  1.31   1 Mar 2001: Rename TSymbol elements to have two leading characters: fixes RTTI bug.
  374.  1.30   1 Mar 2001: Replace color selection combo boxes with TColorEdit.
  375.  1.29   1 Mar 2001: Replace most combobox items with RTTI generated strings.
  376.  1.28  28 Feb 2001: Add Grids due to popular demand (Yuck !).
  377.  1.27  28 Feb 2001: Add the TAxis.StepStart property.
  378.                     Add a scale to ptContour plots.
  379.  1.26  27 Feb 2001: Fix bugs in TSeries.GetNearestPieSlice, and refine TSeries.Outline.
  380.  1.25  26 Feb 2001: Column, Stacked Column and 100% Column plots added to
  381.                     GetTheClickedObject (and TSeriesList.GetNearestPoint).
  382.                     Contemplate releasing next version as 2.0:
  383.                     reason: TPlot now has 10 different plot types, instead of 1 !
  384.  1.24  22 Feb 2001: Refine DrawContour. Implement true WMF and printing. Now looks beautiful !
  385.                     Add usage hints to PropertiesEdit dialog box.
  386.  1.23  21 Feb 2001: Pie plots added to GetTheClickedObject
  387.  1.22  20 Feb 2001: Add OnStyleChange event. Route all "Refresh"s through DoStyleChange.
  388.                     Complete first go at DrawContour.
  389.                     Add ContourDetail property.
  390.  1.21  1 Feb  2001: Add ZAngle, ZLink properties.
  391.                     Rename pSeries.pas unit to Data.pas, SerList.pas to Datalist.pas
  392.  1.20 14 Jan  2001: Modify TSeriesList to add ZData (for 3D)
  393.                     Create TAngleAxis class, and implement a ZAxis for 3D.
  394.                     Add the ptError, ptPie, ptPolar and pt3DWire PlotTypes.
  395.                     Create the NoMath unit, move some stuff into it from Misc.
  396.  1.19 9  Dec  2000: Modify movement of Note Pointer: place before selection of
  397.                     series, and postpend to movement of the Note text.
  398.  1.18 8  Dec  2000: Refine SetPlotType so that each plot type initially displays
  399.                     its features better.
  400.  1.17 6  Dec  2000: Add ptStack and ptNormStack PlotTypes types,
  401.                     and implement their drawing routines.
  402.  1.16 1  Dec  2000: Add ColumnGap property.
  403.  1.15 16 Nov  2000: Implement TNote functionality: NewNote, DeleteNote, etc.
  404.  1.14 13 Nov  2000: Add Misc.TextOutVertical, and employ in various locations;
  405.                     benefit: will work under Linux (look into native X calls later).
  406.  1.13  7 Nov  2000: Add sLeftDash and sRightDash to TSymbol, and to TSeries.DrawSymbol.
  407.  1.12  1 Nov  2000: Create TNote sub-component.
  408.  1.11 16 Oct  2000: Add "Compress Series" and "Compress All Series", and associated
  409.                     CompressSeriesClick and CompressAllSeriesClick. Tidied up:
  410.                     Contract originally compressed; now it really does contract.
  411.                     Remove ability to clone X Axis.
  412.                     Add LabelText to Axes, mainly for Column usage.
  413.                     Fix Instruction property bug in IDE.
  414.  1.10  9 Oct  2000: Add and integrate Column capability with TPlotType type and PlotType properties
  415.                     and TSeriesList.DrawColumns.
  416.                     Consolidate some TCustomPlot.xxxClick methods.
  417.                     ****************************
  418.                     *** Borland BC++ support ***
  419.                     ****************************
  420.  1.02 25 Sept 2000: add and integrate High-Low-Close capability with
  421.                     TSeriesList.DrawMultiple and TSeriesList.DrawHistoryMultiple;
  422.                     Hide menu visibility routine from D1 to avoid 64K problems.
  423.  1.01 21 Sept 2000: fix FontWidth bug in TAxis.Draw
  424.                     add TPlotType type,
  425.                     add PlotType and Multiplicity properties
  426.                     add LabelText property to TAxis (for columns)
  427.       18 Sept 2000: delete PlotList.pas (replaced by SerList.pas);
  428.                     remove GifPng from Plot dpks;
  429.                     re-create saved files.
  430.  1.00 13 Sept 2000: Release version 1.00
  431.  
  432. -----------------------------------------------------------------------------}
  433.  
  434. interface
  435.  
  436. uses
  437.   Classes, SysUtils, TypInfo,
  438. {$IFDEF NO_MATH}NoMath,{$ELSE}Math,{$ENDIF}
  439. {$IFDEF WINDOWS}
  440.   WinTypes, WinProcs,
  441.   Buttons, Clipbrd, Controls, Dialogs,
  442.   Extctrls, Forms, Graphics, Menus, Printers, Stdctrls,
  443. {$ENDIF}
  444. {$IFDEF WIN32}
  445.   Windows,
  446.   Buttons, Clipbrd, ComCtrls, Controls, Dialogs,
  447.   Extctrls, Forms, Graphics, Menus, Printers, Stdctrls,
  448. {$ENDIF}
  449. {$IFDEF LINUX}
  450.   Types, Untranslated,
  451.   QTypes, QButtons, QClipbrd, QComCtrls, QControls, QDialogs,
  452.   QExtctrls, QForms, QGraphics, QImgList, QMenus, QPrinters, QStdctrls,
  453. {$ENDIF}
  454.  
  455. {$IFDEF DELPHI1}
  456.   Metafile,
  457. {$ENDIF}
  458. {$IFDEF GIF}
  459.   GIFImage,
  460. {$ENDIF}
  461. {$IFDEF PNG}
  462.   {$IFDEF MSWINDOWS}
  463.   Pngimage,
  464.   {$ENDIF}
  465. {$ENDIF}
  466.  
  467.   Aboutdlg, Axis, Axisedit, Data, Misc, Optnsdlg, Parser,
  468.   Plotdefs, Plotzoom, Propedit, Datalist, Seredit, Titles;
  469.  
  470. const
  471.   SUBHEADER = 'Subheader';
  472.  
  473. {$IFDEF POLYNOMIAL_FIT}
  474.   POLYORDER = 9;
  475. {$ELSE}
  476.   POLYORDER = 1;
  477. {$ENDIF}
  478.  
  479.  
  480. {$IFDEF DELPHI1}
  481.   DEF_EXTENSION = 'plt';
  482.   PROP_EXTENSION = 'prp';
  483. {$ELSE}
  484.   DEF_EXTENSION = 'plot';
  485.   PROP_EXTENSION = 'props';
  486. {$ENDIF}
  487.  
  488.   crScope = 1;
  489.   crX = 2;
  490.  
  491.   ImageExtensions: array[0..4] of string =
  492.     ('wmf', 'emf', 'bmp', 'gif', 'png');
  493.  
  494. {$IFDEF MSWINDOWS}
  495.   PICTURE_TYPES =
  496.     'Metafile (picture)|*.wmf'
  497.     + '|Enhanced Metafile (picture)|*.emf'
  498.     + '|Bitmap|*.bmp'
  499.   {$IFDEF GIF}
  500.     + '|Compuserve GIF|*.gif'
  501.   {$ENDIF}
  502.   {$IFDEF PNG}
  503.     + '|Web Graphic|*.png'
  504.   {$ENDIF}
  505.     ;
  506. {$ENDIF}
  507. {$IFDEF LINUX}
  508.   PICTURE_TYPES =
  509.     'Metafile picture (*.wmf)'
  510.     + '|Enhanced Metafile picture (*.emf)'
  511.     + '|Bitmap (*.bmp)'
  512.   {$IFDEF GIF}
  513.     + '|Compuserve GIF (*.gif)'
  514.   {$ENDIF}
  515.   {$IFDEF PNG}
  516.     + '|Web Graphic (*.png)'
  517.   {$ENDIF}
  518.     ;
  519. {$ENDIF}
  520.  
  521.  
  522. type
  523. {NB: many other types are in PlotDefs.pas}
  524.   TOnPaintEvent = procedure(Sender: TObject; ACanvas: TCanvas) of object;
  525.  
  526.   TOnFileEvent = procedure(Sender: TObject; TheFile: String) of object;
  527. {When a file is opened or closed, the app can be notified of the new file name
  528.  using this event.}
  529.  
  530.   TOnHeaderEvent = procedure(Sender: TObject; TheStream: TMemoryStream) of object;
  531. {When data is opened, the "user-added" Header (eg: the run date, flow rate,
  532.  comments, etc) is passed back to the user for processing.}
  533.  
  534.   TOnRequestHeaderEvent = procedure(Sender: TObject; TheStream: TMemoryStream) of object;
  535. {When data is saved or copied, then the "user" can add additional data via the
  536.  Header: eg: the run date, flow rate, comments, etc.}
  537.  
  538.   TOnRequestHTMLHeaderEvent = procedure(Sender: TObject; Header: TStringList) of object;
  539. {When data is saved or copied, then the "user" can add additional data via the
  540.  Header: eg: the run date, flow rate, comments, etc.}
  541.  
  542.   TOnSelectionEvent = procedure(Sender: TObject; Sel: TRect) of object;
  543. {When the user clicks and drags over a region, this event is fired.}
  544.  
  545.   TOnDualSelectionEvent = procedure(Sender: TObject; Sel1, Sel2: TRect) of object;
  546. {When the user clicks and drags over TWO regions, this event is fired.}
  547.  
  548.  
  549. {******************************************************************************}
  550.   TCustomPlot = class(TCustomPanel)
  551.   private
  552. {property editor variables:}
  553.     FAbout: String;
  554.     FAxesProperties: String;
  555.     FDataProperties: String;
  556.     FProperties: String;
  557.     FSeriesProperties: String;
  558. {The AxisList is created and managed in the Plot unit and TCustomPlot component.
  559.  The specific axes are:
  560.    0 .. X Axis
  561.    1 .. Primary Y Axis
  562.    2 .. Secondary Y Axis
  563.    3 .. Tertiary Y Axis
  564.    4 .. etc.}
  565.     FAxisList: TList;
  566.     FBorder: TBorder;
  567.     FBubbleSize: TPercent;
  568.     FColumnGap: TPercent;
  569.     FContourDetail: TContourDetail;
  570.     FContourInterval: Single;
  571.     FContourStart: Single;
  572.     FContourWireFrame: Boolean;
  573. {$IFNDEF DELPHI1}
  574.     FCreatedBy: String;
  575.     FDescription: String;
  576. {$ENDIF}
  577.     FDefaultExtension: String;
  578.     FDisplayMode: TDisplayMode;
  579.     FDisplayHistory: Single;
  580.     FEditable: Boolean;
  581.  
  582.     FFileName,      {D:\Data\Delphi\Plot\Test3.csv}
  583.      {GetFileExtension, {csv}
  584.      {GetFileDriveDir,  {D:\Data\Delphi\Plot}
  585.      {GetFileName,      {Test3.csv}
  586.      {GetFileRoot,      {Test3}
  587. {where are the file types ?}
  588.      OpenDriveDir,      {NB: SavePath == FileDriveDir}
  589.      OverlayDriveDir,   {T:\Projects\}
  590.      ImageDriveDir,     {D:\Data\Images}
  591.      PropsFileName: String;
  592. {What file types ?}
  593.      OpenFilterIndex,
  594.      SaveFilterIndex,
  595.      ImageFilterIndex: Integer;
  596.  
  597.     FGrid: TGridType;
  598.     FGridStyle: TPenStyle;
  599.     FGridColor: TColor;
  600.     FHelpFile: String;
  601.     FHighFont: TFont;
  602.     FInstructions: TStringList;
  603. {The Legend of Series}
  604.     FLegend: TLegend;
  605.     FMenuTag: Integer;      {may publish later}
  606.     FMovable: Boolean;
  607.     FMultiplePen: TPen;
  608.     FMultiplicity: Byte;
  609.     FMultiJoin1, FMultiJoin2: Integer;
  610.     FPageButtons: array[0..3] of TBitmap;
  611.     FPieRowCount: Byte;
  612.     FPlotMenu: TMainMenu;
  613.     FPlotToolBar: TToolBar;
  614.     FPlotType: TPlotType;
  615.     FPopupOptions: TPopupOptions;
  616.     FPolarRange: Single;
  617.     FPrintOrientation: TPrinterOrientation;
  618.     FOutlineWidth: Integer;
  619. {The results of things like least-squares fits:}
  620.     FResult: TCaption;
  621.     FSaveOptions: TSaveOptions;
  622.      FAsText: Boolean;  {the current, which depends on the file type and is ORed with FSaveOptions}
  623. {the location of the graph title:}
  624.     FScreenJob: TScreenJob;
  625.     FTitle: TTitle;
  626.     FWallColor: TColor;
  627.     FXAxis: TAxis;
  628.     FXYFastAt: Longint;
  629.     FYAxis: TAxis;
  630.     FZAxis: TAngleAxis;
  631.     FZLink: Boolean;
  632.  
  633. {events:}
  634.     FOnAfterPaint: TOnPaintEvent;
  635.     FOnAfterDraw: TOnPaintEvent;
  636.     FOnBeforePaint: TOnPaintEvent;
  637.     FOnBeforeDraw: TOnPaintEvent;
  638.     FOnStyleChange: TNotifyEvent;
  639.     FOnDataChange: TNotifyEvent;
  640.     FOnFileOpen: TOnFileEvent;
  641.     FOnFileClose: TOnFileEvent;
  642.     FOnHeader: TOnHeaderEvent;
  643.     FOnHeaderRequest: TOnRequestHeaderEvent;
  644.     FOnHTMLHeaderRequest: TOnRequestHTMLHeaderEvent;
  645.     FOnSelection: TOnSelectionEvent;
  646.     FOnDualSelection: TOnDualSelectionEvent;
  647.  
  648.  
  649. {the four borders, clickable by the user:}
  650.     LeftBorder: TRectangle;
  651.     TopBorder: TRectangle;
  652.     RightBorder: TRectangle;
  653.     BottomBorder: TRectangle;
  654.  
  655. {Ignore changes in sub-components during painting:}
  656.     IgnoreChanges: Boolean;
  657.  
  658.  
  659. {The list of (TRectangle descended) objects on screen:}
  660.     ScreenObjectList: TList;
  661.     NoBasicScreenObjects: Integer;
  662. {The list of notes:}
  663.     //NoteList: TList;
  664.     NoteCount: Integer;
  665.  
  666. {The timer to start click-and-drag operations:}
  667.     MouseTimer: TTimer;
  668. {the position of the mousedown:}
  669.     MouseStart: TPoint;
  670.  
  671. {The starting point of click-and-drag operations:
  672.     MouseStart: TPoint; - replaced by Selection1}
  673. {which object(s) were clicked ?}
  674.     ClickedObjectType: TObjectType;
  675.     pClickedObject: Pointer;
  676.     SecondClickedObjectType: TObjectType;
  677.     pSecondClickedObject: Pointer;
  678. {the starting position of the object:}
  679.     ClickedObjectOffset: TPoint;
  680.  
  681. {the parameters of the line of best fit:}
  682.     Slope, Intercept: Single;
  683.     //PolyCoeff: array [0..POLYORDER] of Single;
  684.     
  685. {The rectangular outline of a ScreenObject that is dragged around the screen:}
  686.     Selection: TAngleRect;
  687. {The first selection in a Dual Selection operation:}
  688.     Sel1, Sel2: TRect;
  689.     
  690. {Popup menus:}
  691.     FPlotPopUpMenu: TPopupMenu;
  692.     FDragPopUpMenu: TPopupMenu;
  693.     WhichPopUpMenu: TPopupMenu;
  694.     WhichPopUpItems: array[0..1] of TMenuItem;
  695.  
  696. {the in-place editor:}
  697.     FFlashEdit: TEdit;
  698.  
  699. {the currently selected (eg: by a mouse-click) series:}
  700.     TheSeries: Integer;
  701.     pSeries: TSeries;
  702.     ThePointNumber: Integer;
  703.  
  704. {the currently selected (eg: by a mouse-click) Axis:}
  705.     TheAxis: Integer;
  706.     pAxis: TAxis;
  707.  
  708. {The clipboard format number for HTML:}
  709.     ClipBoardFormatForHTML: Integer; {aka CF_HTML}
  710.  
  711. {Overlay Management:}
  712.     FirstOverlay: Integer;
  713.  
  714.     BevelGap: Integer;
  715.  
  716.     FileExtensions: array[0..3] of String;
  717.    {= (
  718.     FDefaultExtension,
  719.     'csv',
  720.     'txt',
  721.     '*');}
  722.  
  723.     FileTypes: String;
  724.   {=
  725.     'Plot Files|*.' + FDefaultExtension
  726.     + '|Comma Sep Var Files|*.csv'
  727.     + '|Text Files|*.txt'
  728.     + '|All Files|*.*';}
  729.  
  730. {Get functions}
  731.     function GetClickAndDragDelay: Integer;
  732.     function GetNoSeries: Word;
  733.     function GetNoYAxes: Integer;
  734.     function GetSeries(Index: Integer): TSeries;
  735.     function GetNoteFromUser: Boolean;
  736.     function GetSeriesFromUser: Boolean;
  737.     function GetAxisFromUser(StartAxis: Word): Boolean;
  738.     function GetFilterIndex(Ext: String): Integer;
  739. {$IFDEF COMPILER4_UP}
  740. {while TImageList exists from Delphi 2 onwards, TMenu and TPopupMenu
  741.  do not have an Images property until Delphi 4}
  742.     function GetImages: TImageList; {TCustomImageList}
  743.     procedure SetImages(Value: TImageList);
  744. {$ENDIF}
  745.  
  746. {SetProcedures:}
  747. {The main geometry manager.}
  748.     procedure SetAxisDimensions;
  749. {Sets the behaviour upon adding new data points.}
  750.     procedure SetDisplayModeHistory(HistoryValue: Single; ScalingValue: TDisplayMode);
  751. {$IFDEF MSWINDOWS}
  752.   {$IFDEF COMPILER2_UP}
  753.     {Puts CreatedBy and Description into the metafile.}
  754.     procedure SetMetafileDescription;
  755.   {$ENDIF}
  756. {$ENDIF}
  757.  
  758. {Responding to mouse events, click & drag:}
  759.     procedure GetTheClickedObject(X, Y: Integer);
  760.     procedure MouseTimeOut(Sender: TObject);
  761.     procedure MoveTheClickedObjectTo(X, Y: Integer);
  762.     procedure OutlineTheClickedObject;
  763.     procedure SetResult(Slope, Intercept, Rsq: Single);
  764.     procedure StretchTheClickedObjectTo(X, Y: Integer);
  765.     procedure SwapEnds;
  766. {These two respond to a user choice between overlaying objects:}
  767.     procedure MoveTheClickedObjectClick(Sender: TObject);
  768.     procedure MoveSecondClickedObjectClick(Sender: TObject);
  769. {Sets the width of the outline for screen objects like lines: axes and borders.}
  770.     procedure CreateFlashEditor;
  771.     procedure FlashEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  772. {Processes key presses from the in-place editor.}
  773.     procedure FlashEditExit(Sender: TObject);
  774.  
  775.   protected
  776.     FSeriesList: TSeriesList;
  777. {Huh ?! Why protected for both the internal variable and the property ?}
  778. {Because the property is later Published in TPlot, and TDBPlot needs access to
  779.  the internal variable, but still has to hide the property.}
  780.  
  781.     function GetMultiJoin: String;
  782.     function GetZAngle: Word;
  783.     function GetZLength: Word;
  784. {Property Set Procedures:}
  785.     procedure SetZAngle(Value: Word);
  786.     procedure SetZLength(Value: Word);
  787.     procedure SetZLink(Value: Boolean);
  788.     procedure SetXYFastAt(Value: Longint);
  789.     procedure SetBubbleSize(Value: TPercent);
  790.     procedure SetColumnGap(Value: TPercent);
  791.     procedure SetContourDetail(Value: TContourDetail);
  792.     procedure SetContourInterval(Value: Single);
  793.     procedure SetContourStart(Value: Single);
  794.     procedure SetContourWireFrame(Value: Boolean);
  795.     procedure SetGrid(Value: TGridType);
  796.     procedure SetGridStyle(Value: TPenStyle);
  797.     procedure SetGridColor(Value: TColor);
  798.     procedure SetWallColor(Value: TColor);
  799.     procedure SetDefaultExtension(Value: String);
  800.     procedure SetDefaults;
  801.     procedure SetDisplayMode(Value: TDisplayMode);
  802.     procedure SetHistory(Value: Single);
  803.     procedure SetInstructions(Value: TStringList);
  804. {Handles file names for saving and opening:}
  805.     procedure SetFileName(Value: String);
  806.     procedure SetNoYAxes(Value: Integer);
  807.     procedure SetPlotType(Value: TPlotType);
  808.     procedure SetPolarRange(Value: Single);
  809.     procedure SetPopupOptions(Value: TPopupOptions);
  810.     procedure SetOutlineWidth(Value: Integer);
  811.     procedure SetMultiplicity(Value: Byte);
  812.     procedure SetMultiplePen(Value: TPen);
  813.     procedure SetMultiJoin(Value: String);
  814.     procedure SetPieRowCount(Value: Byte);
  815.     procedure SetNoSeries(Value: Word); virtual;
  816.     procedure SetClickAndDragDelay(Value: Integer);
  817.     procedure SetOnSelection(Value: TOnSelectionEvent);
  818.     procedure SetOnDualSelection(Value: TOnDualSelectionEvent);
  819.  
  820.     {procedure StyleChange(Sender: TObject);}
  821. {Responds to appearance changes in subcomponents.}
  822.     {procedure DataChange(Sender: TObject); }
  823. {Responds to changes in the basic data.}
  824.  
  825.  
  826. {Copying data:}
  827.     procedure CopyText; virtual;
  828. {Copies the data as tab-delimited text to the Clipboard, with any
  829.  TCustomPlot.Owner added header.}
  830.     procedure CopyHTML(Format: Word); virtual;
  831. {Copies the data as HTML to the Clipboard in CF_HTML format, with any
  832.  TCustomPlot.Owner added header.}
  833. {Copying pictures:}
  834.     procedure CopyBitmap; virtual;
  835.  
  836.     function GetBitmap: TBitmap; virtual;
  837. {Does what it says.}
  838. {$IFDEF MSWINDOWS}
  839.     function GetDrawing: TMetafile; virtual;
  840. {$ENDIF}
  841. {$IFDEF LINUX}
  842.     function GetDrawing: TDrawing; virtual;
  843. {$ENDIF}
  844. {$IFDEF GIF}
  845.     function GetGIF: TGIFImage; virtual;
  846. {$ENDIF}
  847. {$IFDEF PNG}
  848.   {$IFDEF MSWINDOWS}
  849.     function GetPng: TPngImage; virtual;
  850.   {$ENDIF}
  851.   {$IFDEF LINUX}
  852.     function GetPng: TBitmap; virtual;
  853.   {$ENDIF}
  854. {$ENDIF}
  855.  
  856.     procedure CopyDrawing(Enhanced: Boolean); virtual;
  857. {Does what it says.}
  858.  
  859.     procedure CreateMenus;
  860. {Creates the three popup menus.}
  861.  
  862.     procedure CreatePageButtons;
  863.     procedure DestroyPageButtons;
  864.     procedure PageButtonClick(Index: Integer);
  865.  
  866.     procedure DoStyleChange(Sender: TObject); dynamic;
  867.     procedure DoDataChange(Sender: TObject); dynamic;
  868.     procedure DoFileClose(AFileName: String); dynamic;
  869.     procedure DoFileOpen(AFileName: String); dynamic;
  870.     procedure DoHeader(TheStream: TMemoryStream); dynamic;
  871.     procedure DoHeaderRequest(TheStream: TMemoryStream); dynamic;
  872.     procedure DoHTMLHeaderRequest(TheHeader: TStringList); dynamic;
  873.     procedure DoSelection(Sel1: TRect); dynamic;
  874.     procedure DoDualSelection(Sel1, Sel2: TRect); dynamic;
  875.  
  876. {File manipulation:}
  877.     procedure OpenProperties(AFileName: String);
  878. {Saves the Plot Properties to a file.}
  879.     procedure SaveTheProperties(AFileName: String);
  880. {Saves the Plot Properties to a file.}
  881.  
  882.     function CanPaste: Boolean;
  883. {Can we paste data from the Clipboard into TPlot ?}
  884.     procedure DblClick; override;
  885. {Some items - ie: the Title Captions, can be edited directly.}
  886.     {procedure KeyDown(var Key: Word; Shift: TShiftState); override;}
  887. {This processes certain key strokes.}
  888.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  889. {Implements dragging with the mouse.}
  890.     procedure MouseMove(Shift: TShiftState; X,Y: Integer); override;
  891. {Further implements dragging with the mouse.}
  892.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,Y: Integer); override;
  893. {Implements dragging with the mouse, and right clicking for a popup menu.}
  894.     procedure ProcessClickedObject(pObject: Pointer; TheObjectType: TObjectType); virtual;
  895. {Applies effects of clicking and dragging to the selected object.}
  896.  
  897. {Paint and Draw:}
  898.     procedure DrawGrid(ACanvas: TCanvas);
  899. {This draws grid for xy-type plots - it is called by Draw.}
  900.     procedure DrawWalls(ACanvas: TCanvas);
  901. {This draws XY, XZ and YZ grids for 3D plots - it is called by Draw.}
  902.     procedure Paint; override;
  903. {The normal paint procedure. Most of the work is done in Draw.}
  904.     procedure DrawInstructions;
  905. {Just draws the instructions.}
  906.     procedure Resize; override;
  907. {The normal Resize procedure - it manages screen geometry.}
  908.     procedure ZeroScreenStuff; dynamic;
  909. {This re-initializes all the mouse-selection related variables}
  910.  
  911. {$IFNDEF DELPHI1}
  912.     procedure DetermineMenuVisibility;
  913. {Sets the Visibility of the items of the internal Popup Menu.}
  914.     procedure SetSeriesVisibility(Value: Boolean);
  915. {Makes series-related menu items visible or otherwise}
  916.     procedure SetSeriesEnabledness(TheMenu: TMenu);
  917. {Makes the Series-related items of an external menu Enabled or otherwise}
  918. {$ENDIF}
  919.  
  920. {Properties that will be published in the non-custom descendant:}
  921.     Property About: string read FAbout write FAbout {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  922. {Displays the "About" dialog box for this component.}
  923.     Property AxesProperties: string read FAxesProperties write FAxesProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  924. {Displays the "Axis Editor" dialog box for the FAxisList subcomponent.}
  925.     Property DataProperties: string read FDataProperties write FDataProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  926. {Displays the "Data Editor" dialog box.}
  927.     Property Properties: string read FProperties write FProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  928. {Displays the "Property Editor" dialog box.}
  929.     Property SeriesProperties: string read FSeriesProperties write FSeriesProperties {$IFDEF DELPHI2_UP}stored False{$ENDIF};
  930. {Displays the "Series Editor" dialog box.}
  931.  
  932.     Property AxisList: TList read FAxisList {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  933. {This is a list of all the axes. The 0th is X, the 1st Y.}
  934.  
  935.     Property Bitmap: TBitmap read GetBitmap;
  936. {This returns a Bitmap of the Plot.}
  937. {$IFDEF MSWINDOWS}
  938.     Property Drawing: TMetafile read GetDrawing;
  939.   {This returns a Metafile/Drawing of the Plot.}
  940. {$ENDIF}
  941. {$IFDEF LINUX}
  942.     Property Drawing: TDrawing read GetDrawing;
  943.   {This returns a Metafile/Drawing of the Plot.}
  944. {$ENDIF}
  945. {$IFDEF GIF}
  946.     Property GIF: TGIFImage read GetGIF;
  947. {This returns a Bitmap of the Plot IN GIF FORMAT.}
  948. {$ENDIF}
  949. {$IFDEF PNG}
  950.   {$IFDEF MSWINDOWS}
  951.     Property Png: TPngimage read GetPng;
  952.   {$ENDIF}
  953.   {$IFDEF LINUX}
  954.     Property Png: TBitmap read GetPng;
  955. {This returns a Bitmap of the Plot IN PNG FORMAT.}
  956.   {$ENDIF}
  957. {$ENDIF}
  958.  
  959.     Property PlotPopUpMenu: TPopupMenu read FPlotPopUpMenu;
  960. {The public exposure of the popupmenu for PlotMenu's use.}
  961.     Property Series[Index: Integer]: TSeries read GetSeries {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF}; default;
  962. {This provides direct access to the series maintained by SeriesList.}
  963.     Property SeriesList: TSeriesList read FSeriesList {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  964. {This is the data in a list of data series.}
  965.  
  966.     Property ScreenJob: TScreenJob read FScreenJob write FScreenJob {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  967. {This is the job that is in progress in response to user input.}
  968.  
  969. {Displays the "Series Editor" dialog box.}
  970.     Property Border: TBorder read FBorder write FBorder;
  971. {Manages the geometry of TCustomPlot: where the axes are, where they can go, etc.}
  972.     Property BubbleSize: TPercent read FBubbleSize write SetBubbleSize;
  973. {This is the percentage size of Bubbles, compared to the Y Axis, in the ptBubble PlotType.}
  974.     Property ColumnGap: TPercent read FColumnGap write SetColumnGap;
  975. {This is the percentage gap between groups of Columns in ptColumn PlotType.}
  976.     Property ContourDetail: TContourDetail read FContourDetail write SetContourDetail;
  977. {This is the detail of the colour interpolation in a contour graph.
  978.      cdLow: each triangular tile has uniform colour; this is pretty grainy
  979.      cdMedium: each pixel in each triangular tile has its own colour: this makes a good bitmap, but a lousy metafile
  980.      cdHigh: each rectangular pixel in each triangular tile has its own colour: this makes a good metafile
  981.  See SeriesList.DrawContour.}
  982.     Property ContourInterval: Single read FContourInterval write SetContourInterval;
  983.     Property ContourStart: Single read FContourStart write SetContourStart;
  984.     Property ContourWireFrame: Boolean read FContourWireFrame write SetContourWireFrame;
  985.     
  986.     Property Grid: TGridType read FGrid write SetGrid;
  987. {Do we want a grid in XY-type plots ?}
  988.     Property GridStyle: TPenStyle read FGridStyle write SetGridStyle;
  989. {What pen style (dash, dot, etc) do we want for Grids ?}
  990.     Property GridColor: TColor read FGridColor write SetGridColor default clGray;
  991. {What colour is our grid ? Default is clGray.}
  992.     Property WallColor: TColor read FWallColor write SetWallColor;
  993. {What colour is our Wall ? Default is clYellow.}
  994.     Property HelpFile: String read FHelpFile write FHelpFile;
  995. {When this is set to "", TPlot uses Plot.hlp as its context-sensitive help file.}
  996. {}
  997. {When set to some other file, it uses that instead.}
  998.     Property Instructions: TStringList read FInstructions write SetInstructions;
  999. {This is a message to the user, at the bottom-left of the graph, in the current
  1000.  Font. It disappears on a MouseDown event.}
  1001.  
  1002.     Property ClickAndDragDelay: Integer read GetClickAndDragDelay write SetClickAndDragDelay;
  1003. {The delay (in milliseconds) before a clicked object becomes draggable.}
  1004.  
  1005. {$IFNDEF DELPHI1}
  1006.     Property CreatedBy: String read FCreatedBy write FCreatedBy;
  1007. {A string that is stored in the metafile description.}
  1008. {}
  1009. {This is also used as the "Author" value in a PNG file, if PNG is defined.}
  1010.     Property Description: String read FDescription write FDescription;
  1011. {A string that is stored in the metafile description.}
  1012. {}
  1013. {This is also used as the "Description" value in a PNG file, if PNG is defined.}
  1014. {$ENDIF}
  1015.  
  1016.     Property DisplayHistory: Single read FDisplayHistory write SetHistory;
  1017. {The width of the X Axis when in History mode.}
  1018.     Property DisplayMode: TDisplayMode read FDisplayMode write SetDisplayMode;
  1019. {See TDisplayMode.}
  1020.     Property Editable: Boolean read FEditable write FEditable;
  1021. {Are screen objects like axes Editable ?}
  1022.  
  1023.     Property DefaultExtension: String read FDefaultExtension write SetDefaultExtension;
  1024. {What is the default extension of Plot files ?}
  1025.  
  1026.     Property FileName: String read FFileName write SetFileName {$IFDEF DELPHI2_UP}stored FALSE{$ENDIF};
  1027. {This is the FileName to which the data is saved, or opened from.}
  1028. {}
  1029. {If FileName is blank, and an OpenClick or SaveClick occurs, then the standard
  1030.  file dialog box appears to let the user pick a name.}
  1031.  
  1032.     property HighFont: TFont read FHighFont write FHighFont;
  1033. {The font for annotation of the Highs and Lows.}
  1034. {$IFDEF COMPILER4_UP}
  1035.     property Images: TImageList read GetImages write SetImages; {TCustomImageList}
  1036. {The images for the popupmenu.}
  1037. {$ENDIF}
  1038.     property Legend: TLegend read FLegend write FLegend;
  1039. {The list of series with their line styles. This is a moveable, on-screen object.}
  1040.     property MultiplePen: TPen read FMultiplePen write SetMultiplePen;
  1041. {The pen to use for the verticle lines of ptMultiple PlotTypes (eg: High-Low).}
  1042.     property MultiJoin: String read GetMultiJoin write SetMultiJoin;
  1043. {Which two series, by number, to join with one rectangular symbol, in a ptMultiple plot.
  1044.  Eg: if Multiplicity is 4, and MultiJoin = '2,3', then you have a "Candle" or
  1045.  High-Low-Open-Close plot.}    
  1046.     Property PlotType: TPlotType read FPlotType write SetPlotType;
  1047. {What type of plot is this ?}
  1048.     Property PolarRange: Single read FPolarRange write SetPolarRange;
  1049. {What does 360░ correspond to in a polar graph ? Examples are:
  1050.     2 Pi (6.28...),
  1051.     360 (degrees),
  1052.     60 (minutes),
  1053.     24 (hours)
  1054.     100 (%)
  1055. Get the idea ?    }
  1056.     Property PopupOptions: TPopupOptions read FPopupOptions write SetPopupOptions;
  1057. {If true, then these popup menu items are visible.}
  1058.     Property Movable: Boolean read FMovable write FMovable;
  1059. {Are screen objects like axes movable ?}
  1060.     Property Multiplicity: Byte read FMultiplicity write SetMultiplicity;
  1061. {When the PlotType is ptMultiple, the series are grouped into multiples of Multiplicity.
  1062.  Otherwise ignored.}
  1063.     Property PieRowCount: Byte read FPieRowCount write SetPieRowCount;
  1064. {The number of rows of Pie Graphs.}
  1065.     Property NoSeries: Word read GetNoSeries write SetNoSeries;
  1066. {The number of Series. Setting this can both create new series or free existing series.}
  1067.     Property NoYAxes: Integer read GetNoYAxes write SetNoYAxes;
  1068. {The total number of Y Axes (primary, secondary, tertiary, etc).}    
  1069.     Property PrintOrientation: TPrinterOrientation
  1070.       read FPrintOrientation write FPrintOrientation;
  1071. {Shall we print the graph in Landscape or Portrait mode ?}
  1072.     Property OutlineWidth: Integer read FOutlineWidth write SetOutlineWidth;
  1073. {This is the width of the outline for screen objects like lines: axes and borders.}
  1074.     Property SaveOptions: TSaveOptions read FSaveOptions write FSaveOptions;
  1075. {Shall we save the data as Text or binary ?}
  1076. {}
  1077. {Shall we also save the Plot properties when we save the data ?
  1078.  If we do, then we:
  1079.     1. Save the properties in a seperate file;
  1080.     2. Look for a properties file to open.}
  1081.     Property Title: TTitle read FTitle write FTitle;
  1082. {The title of the graph, including its geometry, font and visibility.}
  1083.     Property XAxis: TAxis read FXAxis write FXAxis;
  1084. {This is the X Axis. Every nice graph should have an X Axis.}
  1085.     Property YAxis: TAxis read FYAxis write FYAxis;
  1086. {This is the Y Axis. Every nice graph should have at least one Y Axis.}
  1087. {}
  1088. {Each Series must know what Y Axes it is being plotted against:
  1089.  Primary (this one) or Secondary.}
  1090.     Property ZAxis: TAngleAxis read FZAxis write FZAxis;
  1091. {This is the Z Axis. Every nice 3D graph should have an Z Axis.}
  1092. {}
  1093. {This is fairly experimental at the moment, so use with caution.
  1094.  It is also nil with non-3D PlotTypes.}
  1095.     Property ZAngle: Word read GetZAngle write SetZAngle;
  1096. {The angle made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  1097.     Property ZLength: Word read GetZLength write SetZLength;
  1098. {The Length made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  1099.     Property ZLink: Boolean read FZLink write SetZLink;
  1100. {Should we link 3D series together in the Z direction ?}
  1101.     Property XYFastAt: Longint read FXYFastAt write SetXYFastAt default 10000;
  1102. {At how many data points should we switch to a fast drawing alforithm.}
  1103.  
  1104. {Events:}
  1105.     Property OnAfterPaint: TOnPaintEvent read FOnAfterPaint write FOnAfterPaint;
  1106.     Property OnAfterDraw: TOnPaintEvent read FOnAfterDraw write FOnAfterDraw;
  1107.     Property OnBeforePaint: TOnPaintEvent read FOnBeforePaint write FOnBeforePaint;
  1108.     Property OnBeforeDraw: TOnPaintEvent read FOnBeforeDraw write FOnBeforeDraw;
  1109.  
  1110.     Property OnStyleChange: TNotifyEvent read FOnStyleChange write FOnStyleChange;
  1111.     Property OnDataChange: TNotifyEvent read FOnDataChange write FOnDataChange;
  1112.  
  1113.     Property OnFileOpen: TOnFileEvent read FOnFileOpen write FOnFileOpen;
  1114. {When a file is opened, the app can be notified of the new file name using this event.}
  1115.  
  1116.     Property OnFileClose: TOnFileEvent read FOnFileClose write FOnFileClose;
  1117. {When a file is closed, the app can be notified of the new file name using this event.}
  1118.  
  1119.     Property OnHeader: TOnHeaderEvent read FOnHeader write FOnHeader;
  1120. {When data is opened, this event passes the header information back to the "user".}
  1121.  
  1122.     Property OnHeaderRequest: TOnRequestHeaderEvent read FOnHeaderRequest write FOnHeaderRequest;
  1123. {When data is saved or copied, this event allows the user to add a header
  1124.  to the data.}
  1125.  
  1126.     Property OnHTMLHeaderRequest: TOnRequestHTMLHeaderEvent read FOnHTMLHeaderRequest write FOnHTMLHeaderRequest;
  1127. {When data is copied as HTML, this event allows the user to add a header
  1128.  to the data.}
  1129.  
  1130.     Property OnSelection: TOnSelectionEvent read FOnSelection write SetOnSelection;
  1131. {When the user selects a region, then this event is fired.}
  1132. {}
  1133. {Note that after firing, this event is set to nil, so you have to reset it every usage.}
  1134.     Property OnDualSelection: TOnDualSelectionEvent read FOnDualSelection write SetOnDualSelection;
  1135. {When the user selects TWO regions, then this event is fired.}
  1136. {}
  1137. {Note that after firing, this event is set to nil, so you have to reset it every usage.}
  1138.  
  1139.   public
  1140.     Constructor Create(AOwner: TComponent); override;
  1141. {The usual Constructor, where sub-components are created, properties set, etc.}
  1142.     Destructor Destroy; override;
  1143. {The usual Destructor, where sub-components are destroyed.}
  1144.  
  1145.     procedure Clear(Cancellable: Boolean); virtual;
  1146. {Saves any changed files (at user request) and then clears the SeriesList.}
  1147.  
  1148.     procedure Draw(ACanvas: TCanvas); virtual;
  1149. {This draws the graph on a Canvas. The canvas can be:}
  1150. {}
  1151. {    1. Self.Canvas - ie: on screen;}
  1152. {    2. a Bitmap, for copying and saving.}
  1153. {    3. a MetafileCanvas, for copying and saving.}
  1154. {    4. the printer.}
  1155. {}
  1156. {It is called by Paint, and also many of the copying and saving routines.}
  1157.  
  1158.     function GetFileExtension: String; {csv}
  1159.     function GetFileDriveDir: String;  {D:\Data\Delphi\Plot}
  1160.     function GetFileRoot: String;      {Test3}
  1161.  
  1162.     function GetPlotTypeAsString: String;
  1163.  
  1164.     procedure ShowAbout;
  1165. {This displays the components "About" dialog box.}
  1166.     procedure ShowAxes;
  1167. {This displays the properties of the Series in the SeriesList.}
  1168.     procedure ShowData;
  1169. {This displays the properties of the Data in the DataList.}
  1170.     procedure ShowProperties;
  1171. {This displays the properties of the Plot.}
  1172.     procedure ShowSeries;
  1173. {This displays the properties of the Series in the SeriesList.}
  1174.  
  1175. {Wrappers for the SeriesList functions; the first three also set the
  1176.  OnStyleChange event and the Visibility property:}
  1177.     function AddSeries(XSeriesIndex: Integer): Integer; virtual;
  1178. {This adds a new, empty series to the list.}
  1179.     function AddExternalSeries(XPointer, YPointer: pSingleArray; NumberOfPoints: Integer): Integer; virtual;
  1180. {This adds a new, empty series to the list, and sets its data to point to the
  1181.  external XPointer, YPointer data.}
  1182.     function AddInternalSeries(XPointer, YPointer: pSingleArray; NumberOfPoints: Integer): Integer; virtual;
  1183. {This adds a new, empty series to the list, and copies the data from the
  1184.  XPointer, YPointer data.}
  1185.     function CloneSeries(TheSeries: Integer): Integer; virtual;
  1186. {This adds a new, empty series to the list, copies the data and properties from
  1187.  TheSeries into the new clone, and changes the color and Y Displacement.}
  1188.     procedure DeleteSeries(Index: Integer); virtual;
  1189. {This deletes TheSeries from the list.}
  1190.  
  1191. {$IFNDEF DELPHI1}
  1192.     procedure DetermineMenuEnabledness(TheMenu: TMenu);
  1193. {$ENDIF}
  1194.  
  1195.     procedure AddData(NoPoints: Integer; XYArray: pXYArray); virtual;
  1196. {Add a slice of readings to the internal series.
  1197.  These will become the Nth points in every series.}
  1198. {}
  1199. {This method is extremely useful for data acquisition.}
  1200.  
  1201.     procedure Trace;
  1202. {This draws all the Series in an erasable mode without re-drawing the Axes,
  1203.  Titles or Legend.}
  1204. {}
  1205. {More specifically, the first call to Trace draws the Series, the second erases them.}
  1206. {}
  1207. {This is useful for rapidly changing data such as an oscilloscope. To use it:}
  1208. {}
  1209. {    1. Set up the Axes, etc.}
  1210. {    2. Create each Series you need.}
  1211. {    3a. Use AllocateNoPts for each one, or:}
  1212. {    3b. Allocate and manage the memory yourself, then use PointToData.}
  1213. {    4. Dump you data into each Series via the XData and YData properties.}
  1214. {    5. Trace the data.}
  1215. {    6. Get more data.}
  1216. {    7. Trace the data again to erase the old image.}
  1217. {    8. Repeat steps (4)-(7) indefinitely.}
  1218. {}
  1219. {Note that in step (4), you can either use the XData and YData properties as:}
  1220. {}
  1221. {    a. pSeries.XData^[i];}
  1222. {    b. pX, pY: pSingle; pX := pSeries.XData; pY := pSeries.YData;}
  1223.  
  1224.     procedure CopyClick(Sender: TObject);
  1225. {This responds to a user selection of "Copy" in the popupmenu,
  1226.  and copies the data as text, as a bitmap, and as an enhanced metafile.}
  1227.     procedure HideClick(Sender: TObject);
  1228. {This hides (.Visible := FALSE) the selected object.}
  1229.     procedure PrintClick(Sender: TObject);
  1230. {This prints the graph.}
  1231.     procedure ShowAllClick(Sender: TObject);
  1232. {This shows (.Visible := TRUE) ALL objects.}
  1233.     procedure PositionClick(Sender: TObject);
  1234. {This reports the Position of the mouse (right) click.}
  1235.     procedure NearestPointClick(Sender: TObject);
  1236. {This reports the Position of the nearest data series point to the mouse
  1237.  (right) click.}
  1238.     procedure DeleteSeriesClick(Sender: TObject);
  1239. {This deletes the currently selected series.}
  1240.  
  1241.     procedure CopySeriesClick(Sender: TObject);
  1242. {This copies the selected series to the clipboard in tab-delimited form.}
  1243.     procedure NewSeriesClick(Sender: TObject);
  1244. {This creates a new, empty series.}
  1245.     procedure CloneSeriesClick(Sender: TObject);
  1246. {This creates a new series, and copies the data of the selected series  into it.}
  1247.     procedure ModeClick(Sender: TObject);
  1248.     {procedure ModeNoneClick(Sender: TObject);
  1249.     procedure ModeRunClick(Sender: TObject);
  1250.     procedure ModeHistoryClick(Sender: TObject);}
  1251. {This sets the Display Mode of the graph.}
  1252.     procedure PasteClick(Sender: TObject);
  1253. {This pastes (Tab Delimited) data from the clipboard.}
  1254.     procedure LineBestFitClick(Sender: TObject);
  1255. {This initiates a line of best fit determination.}
  1256.     procedure TwoRegionLineBestFitClick(Sender: TObject);
  1257. {This initiates a line of best fit determination over two different regions.}
  1258. {$IFDEF FUNCTIONS}
  1259.     procedure FunctionClick(Sender: TObject);
  1260. {This creates a new series which is a function of the existing series.}
  1261. {$ENDIF}
  1262.     procedure SmoothSeriesClick(Sender: TObject);
  1263. {This smoothes the currently seleccted data series.}
  1264.     procedure CompressSeriesClick(Sender: TObject);
  1265. {This Compresss the currently selected data series by a factor of 2, 3, 4, etc.}
  1266.     procedure CompressAllSeriesClick(Sender: TObject);
  1267. {This Compresss ALL data series by a factor of 2, 3, 4, etc.}
  1268.     procedure ContractSeriesClick(Sender: TObject);
  1269. {This contracts the currently selected data series by a factor of 2, 3, 4, etc.}
  1270.     procedure ContractAllSeriesClick(Sender: TObject);
  1271. {This contracts ALL data series by a factor of 2, 3, 4, etc.}
  1272.  
  1273.     procedure LegendClick(Sender: TObject);
  1274. {This responds to a user selection of "Legend" in the popupmenu.}
  1275.     procedure EditAxisClick(Sender: TObject);
  1276. {This responds to a user selection of "Axis ..." in the popupmenu,
  1277.  runs the Edit Axis Dialog, and assigns any changes to the appropriate axis.}
  1278.     procedure ApplyAxisChange(Sender: TObject);
  1279. {Apply changes from the AxisEditor to the Axes.}
  1280.     procedure NewNoteClick(Sender: TObject);
  1281. {This responds to a user selection of "New Note ..." in the popupmenu,
  1282.  creates the note, and gets the user to set it and place it.}
  1283.     procedure MoveNotePointerClick(Sender: TObject);
  1284. {This responds to a user selection of "Move Note Pointer" in the popupmenu,
  1285.  and gets the user to move it and place it.}
  1286.     procedure DeleteNoteClick(Sender: TObject);
  1287. {This responds to a user selection of "Delete Note ..." in the popupmenu,
  1288.  checks with the user, then deletes it.}
  1289.     procedure EditFontClick(Sender: TObject);
  1290. {This responds to a user selection of "Font ..." in the popupmenu,
  1291.  runs the FontDialog, and assigns any changes to the appropriate object.}
  1292.     procedure EditPointClick(Sender: TObject);
  1293. {This responds to a user selection of "Point ..." in the popupmenu,
  1294.  runs the Series.PointEdit method, which displays and runs the PointEditor.}
  1295.     procedure EditDataClick(Sender: TObject);
  1296. {This responds to a user selection of "Edit ... Data ..." in the popupmenu,
  1297.  and displays and runs the DataEditor.}
  1298.     procedure EditSeriesClick(Sender: TObject);
  1299. {This responds to a user selection of "Edit ... Series ..." in the popupmenu,
  1300.  and displays and runs the SeriesEditor.}
  1301.     procedure ApplySeriesChange(Sender: TObject);
  1302. {Apply changes from the SeriesEditor to the Series.}
  1303.  
  1304.     procedure ResetDisplacementClick(Sender: TObject);
  1305. {This sets the Displacement properties DeltaX and DeltaY to ZeroScreenStuff.}
  1306.     procedure EditPropertiesClick(Sender: TObject);
  1307. {This responds to a user selection of "Properties ..." in the popupmenu,
  1308.  runs the PropertiesDialog, and assigns any changes to the appropriate objects.}
  1309.     procedure ApplyPropertiesChange(Sender: TObject);
  1310. {This applies changes from the PropertiesDialog.}
  1311.  
  1312.     procedure NewClick(Sender: TObject);
  1313. {This responds to a user selection of "New" in the File popupmenu,
  1314.  and clears all the data and resets the graph.}
  1315.  
  1316. {$IFDEF FINANCE}
  1317. {Now all the financial functions:}
  1318.     procedure ADLClick(Sender: TObject);
  1319. {This runs the ADL financial calculation.}
  1320. {$ENDIF}
  1321.  
  1322.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1323. {needed by D1 for PlotMenu insertion/removal}
  1324.  
  1325.     procedure OpenClick(Sender: TObject);
  1326. {This responds to a user selection of "Open ..." in the popupmenu,
  1327.  runs the Open Dialog, and calls the LoadFromFile method.}
  1328.     procedure OpenFile(TheFile: String);
  1329.  
  1330.     procedure ClearOverlaysClick(Sender: TObject);
  1331. {This responds to a user selection of "Clear Overlays" in the popupmenu,
  1332.  and removes any Overlays.}
  1333.     procedure OverlayClick(Sender: TObject);
  1334. {This responds to a user selection of "Overlay Data" in the popupmenu,
  1335.  runs the Overlay Dialog, and calls the LoadFromFile method.}
  1336.     procedure SaveImageClick(Sender: TObject);
  1337. {This responds to a user selection of "Save Image" in the popupmenu,
  1338.  runs the Save Dialog, and calls the SaveAsBitmap, SaveAsGIF or the SaveAsDrawing method.}
  1339.     procedure SaveClick(Sender: TObject);
  1340. {This responds to a user selection of "Save Data" in the popupmenu,
  1341.  runs the Save Dialog if FileName is blank, and calls the SaveToFile method.}
  1342.     procedure SaveAsClick(Sender: TObject);
  1343. {This responds to a user selection of "Save Data As" in the popupmenu,
  1344.  runs the Save Dialog, and calls the SaveToFile method.}
  1345.     procedure LoadFromFile(AFileName: String); virtual;
  1346. {Loads the data from a file, using LoadFromStream.}
  1347.     procedure LoadFromStream(AStream: TMemoryStream); virtual;
  1348. {Loads the data from a stream.}
  1349.     procedure AppendToFile;
  1350. {Appends the data as text to a text file.}
  1351.     procedure SaveToFile(AFileName: String); virtual;
  1352. {Saves the data as text to a text file, with any TCustomPlot.Owner added header.}
  1353.     procedure SaveToStream(var TheStream: TMemoryStream); virtual;
  1354. {Saves the data to a stream, with any TCustomPlot.Owner added header.}
  1355.  
  1356. {Saving as a picture:}
  1357.     procedure SaveAsBitmap(AFileName: String); virtual;
  1358. {Does what it says.}
  1359.     procedure SaveAsDrawing(AFileName: String); virtual;
  1360. {$IFDEF GIF}
  1361.     procedure SaveAsGIF(AFileName: String); virtual;
  1362. {$ENDIF}
  1363. {Does what it says.}
  1364. {}
  1365. {If GIF is defined (in Plot.inc) then saving as a GIF is enabled.}
  1366. {}
  1367. {Commercial developers note: the use of GIFs requires a license from Unisys:
  1368.  http://www.unisys.com/unisys/lzw/}
  1369.  
  1370. {$IFDEF PNG}
  1371.     procedure SaveAsPNG(AFileName: String); virtual;
  1372. {$ENDIF}
  1373. {Does what it says.}
  1374. {}
  1375. {If PNG is defined (in Plot.inc) then saving as a PNG is enabled.
  1376.  Note that PNG is always enabled under Kylix.}
  1377.  
  1378.     procedure SetAsNormalClick(Sender: TObject);
  1379. {Defines the current view == Mins and Maxes of axes, as the Normal view.}
  1380.     procedure NormalViewClick(Sender: TObject);
  1381. {Zooms the screen the screen to the Normal view.}
  1382.     procedure ManualZoomClick(Sender: TObject);
  1383. {Zooms the screen using a manual dialog box.}
  1384.     procedure ApplyZoom(Sender: TObject);
  1385. {Applies the zoom.}
  1386.     procedure ZoomOutClick(Sender: TObject);
  1387. {Zooms the screen out after a zoom-in operation.}
  1388.  
  1389.     procedure MakeDummyData(NoSteps: Integer);
  1390. {This procedure is used to generate some dummy data for testing purposes.}
  1391.  
  1392.     procedure CopyHTMLClick(Sender: TObject);
  1393. {Copies the data as HTML to the Clipboard in CF_TEXT format, with any
  1394.  TCustomPlot.Owner added header.}
  1395.     procedure DisplaceClick(Sender: TObject);
  1396. {This responds to a user selection of "Displace" in the popupmenu, and runs
  1397.  the Displacement Form, which moves the selected Series from its origin.}
  1398.     procedure DifferentiateClick(Sender: TObject);
  1399. {This responds to a user selection of "Differentiate" in the popupmenu,
  1400.  and replaces the selected series with its differential.
  1401. {}
  1402. {(Hint: Clone the series first !)}
  1403.     procedure HandleClick(Sender: TObject; TheTag: Integer);
  1404. {The externally-exposed event handler for all menu items.}
  1405. {}
  1406. {It is used by TPlotMenu to forward the click event to TPlot, which then passes
  1407.  it onto the appropriate handler method based on the value of TheTag.}
  1408.     function GetIndicesFromTag(TheTag: Integer; var i, j: Integer): Boolean;
  1409. {Get the i and j indices for the menu from the Tag.}
  1410.     procedure IntegrateClick(Sender: TObject);
  1411. {This responds to a user selection of "Integrate" in the popupmenu, and replaces
  1412.  the selected series with its integral.}
  1413. {}
  1414. {(Hint: Clone the series first !)}
  1415.     procedure IntegralClick(Sender: TObject);
  1416. {This responds to a user selection of "Integral" in the popupmenu,
  1417.  and calculates the integral of the selected series over the user-selected
  1418.  (by click-and-drag) range.}
  1419.     procedure SortClick(Sender: TObject);
  1420. {This runs the Sort method.}
  1421.     procedure SplineClick(Sender: TObject);
  1422. {This responds to a user menu click and performs a cubic spline interpolation
  1423.  of  the currently selected data series by calling the Spline method.}
  1424.     function Spline(ASeries: Integer): Integer;
  1425. {This performs a cubic spline interpolation of ASeries by calling the
  1426.  TSeries.Spline method to place the cubic spline into a new data series.}
  1427.     procedure ZoomInClick(Sender: TObject);
  1428. {}
  1429.     procedure HighsClick(Sender: TObject);
  1430. {Finds and displays the Highs (peaks) and/or Lows (troughs) of a series.}
  1431.     procedure MovingAverageClick(Sender: TObject);
  1432. {Calculates and displays the Moving Average of a series.}
  1433.     procedure AverageClick(Sender: TObject);
  1434. {Calculates the Average of a series over a range.}
  1435.     procedure LinearizeClick(Sender: TObject);
  1436. {Linearizes a series over a range.}
  1437.     procedure ZeroClick(Sender: TObject);
  1438. {Zeros a series over a range.}
  1439.     procedure NewYAxisClick(Sender: TObject);
  1440. {Adds a new axis, based on either the selected or last axis.}
  1441.     procedure DeleteAxis(Index: Integer; Confirm: Boolean);
  1442. {Deletes the selected axis.}
  1443.     procedure DeleteAxisClick(Sender: TObject);
  1444. {Deletes the axis selected by the user.}
  1445.     procedure SetPlotMenu(Value: TMainMenu);
  1446. {Sets the PlotMenu property.}
  1447.     procedure SetPlotToolBar(Value: TToolBar);
  1448. {Sets the PlotMenu property.}
  1449.     procedure SetInstructionText(Value: String);
  1450. {Sets the Instructions stringlist by its Text property.}
  1451.   published
  1452.  
  1453.   end;
  1454. {End of declaration of TCustomPlot.}
  1455.  
  1456. {******************************************************************************}
  1457.   TPlot = class(TCustomPlot)
  1458.   protected
  1459.  
  1460.   public
  1461.     Property AxisList;
  1462. {This is a list of all the axes. The 0th is X, the 1st Y.}
  1463.     Property Bitmap;
  1464. {This returns a Bitmap of the Plot.}
  1465.     Property Drawing;
  1466. {This returns a Drawing/metafile of the Plot. Very useful for printing.}
  1467. {$IFDEF GIF}
  1468.     Property GIF;
  1469. {This returns an image of the Plot IN GIF FORMAT.}
  1470. {$ENDIF}
  1471. {$IFDEF LINUX}
  1472.     Property Png;
  1473. {This returns a Bitmap of the Plot IN PNG FORMAT.}
  1474. {$ENDIF}
  1475.     Property PlotPopUpMenu;
  1476. {The public exposure of the popupmenu for PlotMenu's use.}
  1477.     Property Series;
  1478. {This provides direct access to the series maintained by SeriesList.}
  1479.     Property SeriesList;
  1480. {This is the data in a list of data series.}
  1481.  
  1482.     Property ScreenJob;
  1483. {This is the job that is in progress in response to user input.}
  1484.  
  1485.     Property ZAxis;
  1486. {This is the Z Axis. Every nice 3D graph should have an Z Axis.}
  1487. {}
  1488. {This is fairly experimental at the moment, so use with caution.
  1489.  It is also nil with non-3D PlotTypes.}
  1490.  
  1491.   published
  1492. {All the protected properties of TCustomPlot:}
  1493.     Property About;
  1494. {Displays the "About" dialog box for this component.}
  1495.     Property AxesProperties;
  1496. {Displays the "Axis Editor" dialog box for the FAxisList subcomponent.}
  1497.     Property DataProperties;
  1498. {Displays the "Data Editor" dialog box.}
  1499.     Property Properties;
  1500. {Displays the "Property Editor" dialog box.}
  1501.     Property SeriesProperties;
  1502. {Displays the "Series Editor" dialog box.}
  1503.     Property Border;
  1504. {Manages the geometry of TCustomPlot: where the axes are, where they can go, etc.}
  1505.     Property ClickAndDragDelay;
  1506. {The delay (in milliseconds) before a clicked object becomes draggable.}
  1507.     Property ColumnGap;
  1508. {This is the percentage gap between groups of Columns in ptColumn PlotType.}
  1509.     Property ContourDetail;
  1510. {This is the detail of the colour interpolation in a contour graph.
  1511.      cdLow: each triangular tile has uniform colour; this is pretty grainy
  1512.      cdMedium: each pixel in each triangular tile has its own colour: this makes a good bitmap, but a lousy metafile
  1513.      cdHigh: each rectangular pixel in each triangular tile has its own colour: this makes a good metafile
  1514.  See SeriesList.DrawContour.}
  1515.     Property ContourInterval;
  1516.     Property ContourStart;
  1517.     Property ContourWireFrame;
  1518.  
  1519. {$IFNDEF DELPHI1}
  1520.     Property CreatedBy;
  1521. {For a metafile, this is a string that is stored in the metafile.}
  1522.     Property Description;
  1523. {For a metafile, this is a string that is stored in the metafile.}
  1524. {$ENDIF}
  1525.  
  1526.     Property DisplayHistory;
  1527. {The width of the X Axis when in History mode.}
  1528.     Property DisplayMode;
  1529. {See TDisplayMode.}
  1530.     Property DefaultExtension;
  1531. {What is the default extension of Plot files ?}
  1532.     Property Editable;
  1533. {Are screen objects like axes Editable ?}
  1534.     Property FileName;
  1535. {This is the filename to which the data is saved, or opened from.}
  1536. {}
  1537. {If FileName is blank, and an OpenClick or SaveClick occurs, then the standard
  1538.  file dialog box appears to let the user pick a name.}
  1539.     Property Grid;
  1540. {Do we want a grid in XY-type plots ?}
  1541.     Property GridStyle;
  1542. {What pen style (dash, dot, etc) do we want for Grids ?}
  1543.     Property GridColor;
  1544. {What colour is our grid ? Default is clGray.}
  1545.     property HighFont;
  1546. {The font for annotation of the Highs and Lows.}
  1547.  
  1548. {$IFDEF COMPILER4_UP}
  1549.     property Images;
  1550. {A publication of the Popup Menu's Images property}
  1551. {$ENDIF}
  1552.  
  1553.     Property HelpFile;
  1554. {When this is set to "", TPlot uses Plot.hlp as its context-sensitive help file.}
  1555. {}
  1556. {When set to some other file, it uses that instead.}
  1557.  
  1558.     Property Instructions;
  1559. {This is a hint-like message at the bottom of the graph.
  1560.  It used to be Caption - a string - but now has to be a
  1561.  stringlist to be fully Delphi-compatible (to avoid API calls).
  1562.  Remember Kylix !
  1563.  It disappears upon a MouseDown. See Font.}
  1564.  
  1565.     property Legend;
  1566. {The list of series with their line styles. This is a moveable, on-screen object.}
  1567.     Property Movable;
  1568. {Are screen objects like axes movable ?}
  1569.     Property Multiplicity;
  1570. {When the PlotType is ptMultiple, the series are grouped into multiples of Multiplicity.
  1571.  Otherwise ignored.}
  1572.     property MultiplePen;
  1573. {The pen to use for the verticle lines of ptMultiple PlotTypes (eg: High-Low).}
  1574.     property MultiJoin;
  1575. {Which two series, by number, to join with one rectangular symbol, in a ptMultiple plot.
  1576.  Eg: if Multiplicity is 4, and MultiJoin = '2,3', then you have a "Candle" or
  1577.  High-Low-Open-Close plot.}    
  1578.     property PieRowCount;
  1579. {The number of rows of Pie Graphs.}
  1580.     property NoSeries;
  1581. {The number of Series.}
  1582.     property NoYAxes;
  1583. {The total number of Y Axes (primary, secondary, tertiary, etc).}
  1584.     Property OutlineWidth;
  1585. {This is the width of the outline for screen objects like lines: axes and borders.}
  1586.     Property PlotType;
  1587. {What type of plot is this ?}
  1588.     Property PolarRange;
  1589. {What does 360░ correspond to in a polar graph ? Examples are:
  1590.     2 Pi (6.28...),
  1591.     360 (degrees),
  1592.     60 (minutes),
  1593.     24 (hours)
  1594.     100 (%)
  1595. Get the idea ?    }
  1596.     Property PopupOptions;
  1597. {If true, then these popup menu items are visible.}
  1598.     Property PrintOrientation;
  1599. {Shall we print the graph in Landscape or Portrait mode ?}
  1600.     Property SaveOptions;
  1601. {Shall we save the data as Text or binary ?}
  1602. {}
  1603. {Shall we also save the Plot properties when we save the data ?
  1604.  If we do, then we:
  1605.     1. Save the properties in a seperate file;
  1606.     2. Look for a properties file to open.}
  1607.     Property Title;
  1608. {The title of the graph, including its geometry, font and visibility.}
  1609.     Property WallColor;
  1610. {What colour is our Wall ? Default is clYellow.}
  1611.     Property XAxis;
  1612. {This is the X Axis. Every nice graph should have an X Axis.}
  1613.     Property YAxis;
  1614. {This is the Y Axis. Every nice graph should have at least one Y Axis.}
  1615. {}
  1616. {Each Series must know what Y Axes it is being plotted against:
  1617.  Primary (this one) or Secondary.}
  1618.     Property ZAngle;
  1619. {The angle made by the Z Axis, if any, with the vertical, in a clockwise direction.}
  1620.     Property ZLink;
  1621. {Should we link 3D series together ?}
  1622.     Property XYFastAt;
  1623. {At how many data points should we switch to a fast drawing alforithm.}
  1624.     
  1625. {Events:}
  1626.     Property OnAfterPaint;
  1627.     Property OnAfterDraw;
  1628.     Property OnBeforePaint;
  1629.     Property OnBeforeDraw;
  1630.     Property OnStyleChange;
  1631.     Property OnDataChange;
  1632.  
  1633.     Property OnFileOpen;
  1634. {When a file is opened, the app can be notified of the new file name using this event.}
  1635.  
  1636.     Property OnFileClose;
  1637. {When a file is closed, the app can be notified of the new file name using this event.}
  1638.  
  1639.     Property OnHeader;
  1640. {When data is opened, this event passes the header information back to the "user".}
  1641.  
  1642.     Property OnHeaderRequest;
  1643. {When data is saved or copied, this event allows the user to add a header
  1644.  to the data.}
  1645.  
  1646.     Property OnHTMLHeaderRequest;
  1647. {When data is copied as HTML, this event allows the user to add a header
  1648.  to the data.}
  1649.  
  1650.     Property OnSelection;
  1651.     Property OnDualSelection;
  1652.  
  1653. {all the "extra" TPanel properties in D4 (alias "VCL Bloat"):}
  1654.  
  1655. {Now all the TPanel properties-------------------------------------------------}
  1656. {all the TPanel properties in D1:}
  1657.     property Align;    
  1658.     {property Alignment;}
  1659.     property BevelInner;
  1660.     property BevelOuter;
  1661.     property BevelWidth;
  1662.     property BorderWidth;
  1663.     property BorderStyle;
  1664.     {property Caption; - replaced by Instructions}
  1665.     property Color;
  1666. {$IFDEF MSWINDOWS}
  1667.     property Ctl3D;
  1668.     property DragCursor;
  1669. {$ENDIF}
  1670.     property DragMode;
  1671.     property Enabled;
  1672.     property Font;
  1673. {This is the font of the hint-like message at the bottom of the graph.}
  1674.     property ParentColor;
  1675. {$IFDEF MSWINDOWS}
  1676.     property Locked;
  1677.     property ParentCtl3D;
  1678. {$ENDIF}
  1679.     property ParentFont;
  1680.     property ParentShowHint;
  1681. { Note: D1 to D4 were quite happy for:
  1682.         PopupMenu := FPlotPopUpMenu;
  1683.   FPlotPopUpMenu was then run by inherited MouseUp.
  1684.   However, D5 introduced TControl.WMContextMenu, which ran BEFORE MouseDown.
  1685.   This went spastic when it tried to Popup the PopupMenu.
  1686.  
  1687.   We have therefore returned to hiding FPlotPopUpMenu, and running it manually.
  1688.     property PopupMenu;}
  1689.     property ShowHint;
  1690.     property TabOrder;
  1691.     property TabStop;
  1692.     property Visible;
  1693.     property OnClick;
  1694.     property OnDblClick;
  1695.     property OnDragDrop;
  1696.     property OnDragOver;
  1697.     property OnEndDrag;
  1698.     property OnEnter;
  1699.     property OnExit;
  1700.     property OnMouseDown;
  1701.     property OnMouseMove;
  1702.     property OnMouseUp;
  1703.     property OnResize;
  1704.  
  1705.     
  1706. {$IFDEF COMPILER2_UP}
  1707. {$ENDIF}
  1708.  
  1709. {$IFDEF COMPILER3_UP}
  1710.   {$IFDEF MSWINDOWS}
  1711.     property FullRepaint;
  1712.     property OnStartDrag;
  1713.   {$ENDIF}
  1714. {$ENDIF}
  1715.  
  1716. {$IFDEF COMPILER4_UP}
  1717.     property Anchors;
  1718.     // property AutoSize; - leads to bizzare behaviour
  1719.   {$IFDEF MSWINDOWS}
  1720.     property BiDiMode;
  1721.   {$ENDIF}
  1722.     property Constraints;
  1723.   {$IFDEF MSWINDOWS}
  1724.     property UseDockManager default True;
  1725.     property DockSite;
  1726.     property DragKind;
  1727.     property ParentBiDiMode;
  1728.     property OnCanResize;
  1729.   {$ENDIF}
  1730.     property OnConstrainedResize;
  1731.   {$IFDEF MSWINDOWS}
  1732.     property OnDockDrop;
  1733.     property OnDockOver;
  1734.     property OnEndDock;
  1735.     property OnGetSiteInfo;
  1736.     property OnStartDock;
  1737.     property OnUnDock;
  1738.   {$ENDIF}
  1739. {$ENDIF}
  1740.  
  1741. {$IFDEF COMPILER5_UP}
  1742. {$ENDIF}
  1743.   end;
  1744.  
  1745.  
  1746. implementation
  1747. {$IFDEF DELPHI1}
  1748. {$R strlist.res}
  1749. {$R Cursor16.res}
  1750. {$ELSE}
  1751. {$R Cursor32.res}
  1752. {$ENDIF}
  1753.  
  1754. uses
  1755.   Plotmenu, Plottoolbar;
  1756.  
  1757. {TCustomPlot methods --------------------------------------------------------------}
  1758. {------------------------------------------------------------------------------
  1759.     Procedure: TCustomPlot.ShowAbout
  1760.   Description: Property editor methods, et cetera
  1761.        Author: Mat Ballard
  1762.  Date created: 12/1/1999
  1763. Date modified: 03/29/2001 by Mat Ballard
  1764.       Purpose: design-time user interface
  1765.  Known Issues: TAboutDlg adds about 8 K to the app
  1766.  ------------------------------------------------------------------------------}
  1767. procedure TCustomPlot.ShowAbout;
  1768. var
  1769.   AboutDlg: TAboutDlg;
  1770.   {Msg: String;}
  1771. begin
  1772.   AboutDlg := TAboutDlg.Create(nil);
  1773.   AboutDlg.Comments :=
  1774.     'TPlot ' + sVersion  + ' ' + FloatToStrF(TPLOT_VERSION / 100, ffFixed, 5, 2) + #10 +
  1775.     sReleasedQ + #10 + #10 +
  1776.     sAcknowledgementsTo + #10 +
  1777.     '  Anders Melanders - TGifImage' + #10 +
  1778.     '  Edmund H. Hand, Dominique Louis, Uberto Barbini' + sAnd + #10 +
  1779.     '    Eric Engler - TPngimage' + #10 +
  1780.     '  Atanas Stoyanov - MemProof' + #10 +
  1781.     '  Renate Schaaf, Alin Flaider, Hallvard Vassbotn' + sAnd + #10 +
  1782.     '    Stefan Hoffmeister - TParser10' + #10 +
  1783.     '  John Shemitz - ' + sRotated + ' Kylix ' + sText;
  1784.     
  1785.   AboutDlg.Execute;
  1786.   AboutDlg.Free;
  1787. end;
  1788.  
  1789. procedure TCustomPlot.ShowData;
  1790. begin
  1791.   EditDataClick(Self);
  1792. end;
  1793.  
  1794. procedure TCustomPlot.ShowSeries;
  1795. begin
  1796.   EditSeriesClick(Self);
  1797. end;
  1798.  
  1799. procedure TCustomPlot.ShowAxes;
  1800. begin
  1801.   EditAxisClick(Self);
  1802. end;
  1803.  
  1804. procedure TCustomPlot.ShowProperties;
  1805. begin
  1806.   EditPropertiesClick(Self);
  1807. end;
  1808.  
  1809. {Constructor and Destructor:-------------------------------------------------}
  1810. {------------------------------------------------------------------------------
  1811.     Procedure: TCustomPlot.Create
  1812.   Description: class constructor
  1813.        Author: Mat Ballard
  1814.  Date created: 12/1/1999
  1815. Date modified: 02/25/2000 by Mat Ballard
  1816.       Purpose: initialize variables and create sub-components
  1817.  Known Issues:
  1818.  ------------------------------------------------------------------------------}
  1819. Constructor TCustomPlot.Create(
  1820.   AOwner:TComponent);
  1821. begin
  1822. {First call the ancestor:}
  1823.   inherited Create(AOwner);
  1824.  
  1825. {we create all objects here, otherwise property changes trigger
  1826.  references to non-existent objects:}
  1827.   FPlotPopUpMenu := TPopupMenu.Create(Self);
  1828. { see note above at 'property PopupMenu':
  1829.   PopUpMenu := FPlotPopUpMenu;}
  1830.   FPopupOptions := TPopupOptions.Create;
  1831.  
  1832.   FInstructions := TStringList.Create;
  1833.  
  1834.   FFlashEdit := nil;
  1835.  
  1836. {create the list of all axes:}
  1837.   FAxisList := TList.Create;
  1838. {create all the Axes:}
  1839.   FXAxis := TAxis.Create(Self);
  1840.   FAxisList.Add(FXAxis);
  1841.   FYAxis := TAxis.Create(Self);
  1842.   FAxisList.Add(FYAxis);
  1843.  
  1844. {create the list of data series:}
  1845.   FSeriesList := TSeriesList.Create(FAxisList);
  1846. {Do things with the series list:}
  1847.  
  1848. {create the border of the graph:}
  1849.   FBorder := TBorder.Create(Self);
  1850.  
  1851. {create the user-clickable edges of the graph (for clicking and dragging):}
  1852.   LeftBorder := TRectangle.Create(Self);
  1853.   TopBorder := TRectangle.Create(Self);
  1854.   RightBorder := TRectangle.Create(Self);
  1855.   BottomBorder := TRectangle.Create(Self);
  1856.  
  1857. {create the graph title:}
  1858.   FTitle := TTitle.Create(Self);
  1859.  
  1860. {The Result of a least-squares fit:}
  1861.   FResult := TCaption.Create(Self);
  1862.  
  1863. {create the plot legend:}
  1864.   FLegend := TLegend.CreateList(Self, FSeriesList);
  1865.  
  1866. {the font for annotation of the highs and lows:}
  1867.   FHighFont := TFont.Create;
  1868.  
  1869.   FMultiplePen := TPen.Create;
  1870.   FMultiJoin1 := 0;
  1871.   FMultiJoin2 := 0;
  1872.  
  1873. {create the object that is clicked and dragged:}
  1874.   Selection := TAngleRect.Create(Self);
  1875.  
  1876. {create the list of objects on the screen:}
  1877.   ScreenObjectList := TList.Create;
  1878.  
  1879. {nil out the page buttons:}
  1880.   FPageButtons[0] := nil;
  1881.   FPageButtons[1] := nil;
  1882.   FPageButtons[2] := nil;
  1883.   FPageButtons[3] := nil;
  1884.  
  1885. {This is a typical size:}
  1886.   Height := 300;
  1887.   Width := 400;
  1888. {Users can edit some screen text:}
  1889.   FEditable := TRUE;
  1890. {Users can move screen objects:}
  1891.   FMovable := TRUE;
  1892.  
  1893. {10% of Y Axis maximum bubble size:}
  1894.   FBubbleSize := 10;
  1895.  
  1896. {20% gap between columns:}
  1897.   FColumnGap := 20;
  1898.  
  1899. {distance between line contours is 1:}  
  1900.   FContourInterval := 1;
  1901.  
  1902. {Dotted grids are the default:}
  1903.   FGridStyle := psDot;
  1904.   FGridColor := clGray;
  1905.   FWallColor := clYellow;
  1906.  
  1907. {our default help file:}
  1908.   FHelpFile := 'Plot.hlp';
  1909.  
  1910. {only one row of pie graphs:}
  1911.   FPieRowCount := 1;
  1912.  
  1913. {High-Low is the default Multiple plot:}
  1914.   FMultiPlicity := 2;
  1915.  
  1916. {One whole rotation corrsponds to ...}
  1917.   FPolarRange := TWO_PI;
  1918.  
  1919.   FZLink := TRUE;
  1920.   FXYFastAt := 10000;
  1921.  
  1922. {No mouse timer as yet:}
  1923.   MouseTimer := TTimer.Create(Self);
  1924.   MouseTimer.Enabled := FALSE;
  1925.   MouseTimer.OnTimer := MouseTimeOut;
  1926.  
  1927. {no series has been selected yet:}
  1928.   pSeries := nil;
  1929.   TheSeries := -1;
  1930.   ClickedObjectType := soNone;
  1931.  
  1932.   FDisplayHistory := 30;
  1933.   FirstOverlay := -1;
  1934.   FPlotMenu := nil;
  1935.   //FPlotActionList := nil;
  1936.   FPrintOrientation := poLandscape;
  1937. {ZeroScreenStuff everything to do with mice:}
  1938.   FScreenJob := sjNone;
  1939.   FOnSelection := nil;
  1940.   FOnDualSelection := nil;
  1941.   FSaveOptions := [soProperties];
  1942.  
  1943.   DefaultExtension := DEF_EXTENSION;
  1944.   FileExtensions[1] := 'csv';
  1945.   FileExtensions[2] := 'txt';
  1946.   FileExtensions[3] := '*';
  1947.  
  1948.   OpenFilterIndex := 1;
  1949.   SaveFilterIndex := 1;
  1950.   ImageFilterIndex := 1;
  1951.  
  1952.   BevelGap := 1;
  1953.  
  1954. {Take the hint:}
  1955.   FInstructions.Add(sInstructionLine1);
  1956.   FInstructions.Add(sInstructionLine2);
  1957.  
  1958. {... and initialize the X-Axis:}
  1959.   FXAxis.Title.Units := sSeconds;
  1960.   FXAxis.Tag := Ord(soXAxis);
  1961.   FXAxis.Labels.Tag := Ord(soXAxisLabel);
  1962.   FXAxis.Title.Tag := Ord(soXAxisTitle);
  1963.   FXAxis.TickDirection := orRight;
  1964.  
  1965. {... and initialize the Y-Axis:}
  1966.   FYAxis.Direction := drVertical;
  1967.   FYAxis.TickDirection := orLeft;
  1968.   FYAxis.Title.Orientation := orLeft;
  1969.   FYAxis.Title.Units := smVolts;
  1970.   FYAxis.Title.Caption := 'Y-' + sAxis;
  1971.   FYAxis.Tag := Ord(soYAxis);
  1972.   FYAxis.Labels.Tag := Ord(soYAxisLabel);
  1973.   FYAxis.Title.Tag := Ord(soYAxisTitle);
  1974.  
  1975. {create the border dimensions of the plot:}
  1976.   SetDefaults;
  1977.  
  1978. {Name the user-clickable edges of the graph (for clicking and dragging):}
  1979.   LeftBorder.Name := sLeft + ' ' + sBorder;
  1980.   LeftBorder.Tag := Ord(soLeftBorder);
  1981.   TopBorder.Name := sTop + ' ' + sBorder;
  1982.   TopBorder.Tag := Ord(soTopBorder);
  1983.   RightBorder.Name := sRight + ' ' + sBorder;
  1984.   RightBorder.Tag := Ord(soRightBorder);
  1985.   BottomBorder.Name := sBottom + ' ' + sBorder;
  1986.   BottomBorder.Tag := Ord(soBottomBorder);
  1987.  
  1988. {... and initialize the Plot Title:}
  1989.   FTitle.Caption := ClassName;
  1990.   FTitle.Name := sPlot + ' ' + sTitle;
  1991.   FTitle.Orientation := orLeft;
  1992.   FTitle.Font.Size := LARGE_FONT_SIZE;
  1993.   FTitle.Tag := Ord(soTitle);
  1994.  
  1995. {The Result of a least-squares fit:}
  1996.   FResult.Font.Size := SMALL_FONT_SIZE;
  1997. {invisibilize it:}
  1998.   FResult.Top := -100;
  1999.   FResult.Tag := Ord(soResult);
  2000.  
  2001. {... and initialize the plot legend:}
  2002.   FLegend.Name := sLegend;
  2003.   FLegend.Font.Size := SMALL_FONT_SIZE;
  2004.   FLegend.Tag := Ord(soLegend);
  2005.  
  2006. {Initialize the Instruction font:}
  2007.   Font.Name := sArial;
  2008.   Font.Size := SMALL_FONT_SIZE;
  2009.   Font.Color := clRed;
  2010. {the font for annotation of the highs and lows:}
  2011.   FHighFont.Name := sArial;
  2012.   FHighFont.Size := SMALL_FONT_SIZE;
  2013.  
  2014. {load the list of screen objects:}
  2015.   ScreenObjectList.Add(Selection);      {soNone}
  2016.   ScreenObjectList.Add(FTitle);         {soTitle}
  2017.   ScreenObjectList.Add(FLegend);        {soLegend}
  2018.   ScreenObjectList.Add(FResult);        {soResult}
  2019.   ScreenObjectList.Add(FXAxis);         {soXAxis}
  2020.   ScreenObjectList.Add(FXAxis.Title);   {soXAxisTitle}
  2021.   ScreenObjectList.Add(FXAxis.Labels);  {soXAxisLabel}
  2022.   ScreenObjectList.Add(FYAxis);         {soYAxis}
  2023.   ScreenObjectList.Add(FYAxis.Title);   {soYAxisTitle}
  2024.   ScreenObjectList.Add(FYAxis.Labels);  {soYAxisLabel}
  2025. {Reserved for the Z axis:}  
  2026.   ScreenObjectList.Add(nil);            {soZAxis}
  2027.   ScreenObjectList.Add(nil);            {soZAxisTitle}
  2028.   ScreenObjectList.Add(nil);            {soZAxisLabel}
  2029.   ScreenObjectList.Add(LeftBorder);     {soLeftBorder}
  2030.   ScreenObjectList.Add(TopBorder);      {soTopBorder}
  2031.   ScreenObjectList.Add(RightBorder);    {soRightBorder}
  2032.   ScreenObjectList.Add(BottomBorder);   {soBottomBorder}
  2033. {Note: NoBasicScreenObjects is this list here.
  2034.  Additional objects (secondary Y Axes, Z Axes, notes, etc,
  2035.  are not counted in this total.}
  2036.   NoBasicScreenObjects := ScreenObjectList.Count;
  2037. {The reason for this is that these latter can be added in any order.}
  2038.  
  2039. {create the list of notes:}
  2040.   //NoteList := TList.Create;
  2041.   NoteCount := 0;
  2042.  
  2043.   SetPlotType(ptXY);
  2044.  
  2045. {set the user-clickable border thicknesses:}
  2046.   SetOutlineWidth(10);
  2047. {this fires SetAxisDimensions.}
  2048.  
  2049.   CreateMenus;
  2050.  
  2051. {Set all the OnStyleChanges:}
  2052.   FXAxis.OnChange := DoStyleChange;
  2053.   FYAxis.OnChange := DoStyleChange;
  2054.   FBorder.OnChange := DoStyleChange;
  2055.   FTitle.OnChange := DoStyleChange;
  2056.   FSeriesList.OnStyleChange := DoStyleChange;
  2057.   FSeriesList.OnDataChange := DoDataChange;
  2058.   FLegend.OnChange := DoStyleChange;
  2059.  
  2060.   Color := clWindow;
  2061.  
  2062. {load some cursors:}
  2063. {$IFDEF MSWINDOWS}
  2064.   Screen.Cursors[crScope] := {WinProcs.}LoadCursor(HInstance, 'crScope');
  2065.   Screen.Cursors[crX] := {WinProcs.}LoadCursor(HInstance, 'crX');
  2066. {$ENDIF}
  2067.   ZeroScreenStuff;
  2068.   IgnoreChanges := FALSE;
  2069.   if (csDesigning in ComponentState) then
  2070.     MakeDummyData(20);
  2071. end;
  2072.  
  2073. {functions called by constructor ----------------------------------------------}
  2074. {set the graph dimensions:}
  2075. procedure TCustomPlot.SetDefaults;
  2076. begin
  2077.   FBorder.Left := 70;
  2078.   FBorder.Top := 40;
  2079.   FBorder.RightEx := Width;
  2080.   FBorder.BottomEx := Height;
  2081.   FBorder.RightGap := 50;
  2082.   FBorder.BottomGap := 80;
  2083. end;
  2084.  
  2085. {------------------------------------------------------------------------------
  2086.     Procedure: TCustomPlot.MakeDummyData
  2087.   Description: procedure to add two series, with sine wave data
  2088.        Author: Mat Ballard
  2089.  Date created: 12/1/1999
  2090. Date modified: 02/25/2000 by Mat Ballard
  2091.       Purpose: 1. test TCustomPlot
  2092.                2. display capabilities in design mode.
  2093.  Known Issues:
  2094.  ------------------------------------------------------------------------------}
  2095. procedure TCustomPlot.MakeDummyData(NoSteps: Integer);
  2096. var
  2097.   i,
  2098.   j: Integer;
  2099.   Amplitude,
  2100.   MidY,
  2101.   Phase,
  2102.   StepSize,
  2103.   X,
  2104.   Y: Single;
  2105.   OldIgnoreChanges: Boolean;
  2106. begin
  2107.   OldIgnoreChanges := IgnoreChanges;
  2108.   IgnoreChanges := TRUE;
  2109. {clean up first:}
  2110.   for i := 0 to FSeriesList.Count-1 do
  2111.   begin
  2112.     TSeries(FSeriesList.Items[i]).DelData;
  2113.   end;
  2114.  
  2115.   if (FSeriesList.Count = 0) then
  2116.   begin
  2117.     FSeriesList.Add(-1);
  2118.     //TSeries(FSeriesList.Items[0]).OnStyleChange := DoStyleChange(Self);
  2119.     case FPlotType of
  2120.       ptError:
  2121.         begin
  2122. {add two series:}
  2123.           FSeriesList.Add(-1);
  2124.           //TSeries(FSeriesList.Items[1]).OnStyleChange := DoStyleChange(Self);
  2125.         end;
  2126.       ptLineContour, ptContour, pt3DContour, pt3DWire, pt3DColumn{, pt3DSurface}:
  2127.         begin
  2128.         end;
  2129.       else
  2130.         begin
  2131. {add two series, the second depending on the first:}
  2132. {this second series uses the X data of the first series:}
  2133.           FSeriesList.Add(0);
  2134.           TSeries(FSeriesList.Items[1]).OnStyleChange := DoStyleChange;
  2135.         end;
  2136.     end; {case}
  2137.   end;
  2138.  
  2139. {seed it:}
  2140.   Randomize;
  2141. {set the phase for trig functions:}
  2142.   Phase := Random;
  2143. {initialize: calculate the step size:}
  2144.   StepSize := (FXAxis.Max - FXAxis.Min) / NoSteps;
  2145. {... and the size:}
  2146.   Amplitude := (FYAxis.Max - FYAxis.Min) / 2;
  2147.   MidY := (FYAxis.Max + FYAxis.Min) / 2;
  2148.   for i := 0 to NoSteps do
  2149.   begin
  2150.     for j := 0 to FSeriesList.Count-1 do
  2151.     begin
  2152.       case FPlotType of
  2153.         ptError, ptBubble:
  2154.           begin
  2155.             if (j mod 2 > 0) then
  2156.             begin
  2157.               X := Random;
  2158.               Y := Random;
  2159.             end
  2160.             else
  2161.             begin
  2162.               X := FXAxis.Min + i * StepSize;
  2163.               Y := MidY + Amplitude * Sin(X + (j+1) * Phase) + Random;
  2164.             end;
  2165.           end;
  2166.         ptPolar:
  2167.           begin
  2168.             X := (i / NoSteps) * Self.FPolarRange;
  2169.             Y := FXAxis.Max / 2 + (Amplitude/3) * Sin(X + (j+1) * Phase);
  2170.           end;
  2171.         ptLineContour, ptContour, pt3DContour, pt3DWire, pt3DColumn{, pt3DSurface}:
  2172.           begin
  2173.             X := FXAxis.Min + i * StepSize;
  2174.             Y := Exp(-j / 2.0) * (MidY + Amplitude * Sin(X));
  2175.           end;
  2176.         else
  2177.           begin
  2178.             X := FXAxis.Min + i * StepSize;
  2179.             Y := MidY + Amplitude * Sin(X + (j+1) * Phase) + Random;
  2180.           end;
  2181.       end; {case}
  2182.       TSeries(FSeriesList.Items[j]).ZData := j;
  2183. {Don't fire any events, and don't adjust axes:}
  2184.       TSeries(FSeriesList.Items[j]).AddPoint(X, Y, FALSE, FALSE);
  2185.     end; {for j}
  2186.   end; {for i}
  2187.   for j := 0 to FSeriesList.Count-1 do
  2188.     TSeries(FSeriesList.Items[j]).Visible := TRUE;
  2189.   IgnoreChanges := OldIgnoreChanges;
  2190.   ZoomOutClick(Self);
  2191. end;
  2192.  
  2193. {------------------------------------------------------------------------------
  2194.     Procedure: TCustomPlot.CreateMenus
  2195.   Description: creates popup menus that are accessible by right-click
  2196.        Author: Mat Ballard
  2197.  Date created: 12/1/1999
  2198. Date modified: 04/20/2000 by Mat Ballard
  2199.       Purpose: modularize user-interface code
  2200.  Known Issues: this was a bitch to get right !
  2201.  ------------------------------------------------------------------------------}
  2202. procedure TCustomPlot.CreateMenus;
  2203. var
  2204.   i, j: Integer;
  2205. {$IFDEF COMPILER4_UP}
  2206.   ImageIndex: Integer;
  2207. {$ENDIF}
  2208.   TagIndex: Longint;
  2209. {This following is just a dummy matrix of menu items used to create sub-menus,
  2210.  then removed and the menuitems freed.}
  2211. {$IFDEF FINANCE}
  2212.   TempMenu: array [0..Ord(mnuFinance)] of array [0..0] of TMenuItem;
  2213. {$ELSE}
  2214.   TempMenu: array [0..Ord(mnuCalc)] of array [0..0] of TMenuItem;
  2215. {$ENDIF}
  2216.   TempMenuItem: TMenuItem;
  2217.   StrResName: String;
  2218.   RightDragItems: array[0..8] of TPoint;
  2219. const
  2220. {$IFDEF FINANCE}
  2221.   MaxIndex = Ord(mnuFinance);
  2222. {$ELSE}
  2223.   MaxIndex = Ord(mnuCalc);
  2224. {$ENDIF}
  2225.  
  2226.   NoMenusItems: array [0..MaxIndex] of Integer =
  2227.     (Ord(mnuPrint),
  2228.      Ord(mnuProperties),
  2229.      Ord(mnuZoomOut),
  2230. {$IFDEF FUNCTIONS}
  2231.      Ord(mnuFunction)
  2232. {$ELSE}
  2233.      Ord(mnuTwoRegionLineOfBestFit)
  2234. {$ENDIF}
  2235. {$IFDEF FINANCE}
  2236.      , Ord(mnuWilliams));
  2237. {$ELSE}
  2238.      );
  2239. {$ENDIF}
  2240.  
  2241.   procedure CreateTempMenu(k: Integer; ACaption: String);
  2242.   begin
  2243. {we create a temporary menu array to add the submenu, and then later remove it:}
  2244.     TempMenu[k][0] := TMenuItem.Create(Self);
  2245. { we used to use the caption, until localization:
  2246.     StrResName := CleanString(ACaption, '&');
  2247.     StrResName := CleanString(StrResName, '.');
  2248.     StrResName := CleanString(StrResName, ' ');
  2249.     StrResName := StrResName + 'SubMenu';}
  2250.     StrResName := 'm' + IntToStr(k);
  2251.     TempMenuItem := NewSubMenu(
  2252.       ACaption,
  2253.       0,
  2254.       StrResName,
  2255.       TempMenu[k]);
  2256.     TempMenuItem.Tag := TagIndex + TAG_BASE;
  2257.     FPlotPopUpMenu.Items.Add(TempMenuItem);
  2258.  
  2259.     Inc(TagIndex);
  2260.   end;
  2261.  
  2262.   procedure CreateOnClicks;
  2263.   begin
  2264.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuNew)].OnClick := NewClick;
  2265.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOpen)].OnClick := OpenClick;
  2266.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlayDiv)].OnClick := nil;
  2267.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlay)].OnClick := OverlayClick;
  2268.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuClearOverlays)].OnClick := ClearOverlaysClick;
  2269.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveDiv)].OnClick := nil;
  2270.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSave)].OnClick := SaveClick;
  2271.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveAs)].OnClick := SaveAsClick;
  2272.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveImage)].OnClick := SaveImageClick;
  2273.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrintDiv)].OnClick := nil;
  2274.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrint)].OnClick := PrintClick;
  2275.  
  2276.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopy)].OnClick := CopyClick;
  2277.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].OnClick := CopyHTMLClick;
  2278.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].OnClick := CopySeriesClick;
  2279.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].OnClick := PasteClick;
  2280.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].OnClick := nil;
  2281.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].OnClick := DisplaceClick;
  2282.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].OnClick := ResetDisplacementClick;
  2283.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].OnClick := nil;
  2284.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewSeries)].OnClick := NewSeriesClick;
  2285.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].OnClick := CloneSeriesClick;
  2286.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].OnClick := EditPointClick;
  2287.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].OnClick := EditDataClick;
  2288.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].OnClick := EditSeriesClick;
  2289.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].OnClick := DeleteSeriesClick;
  2290.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].OnClick := LinearizeClick;
  2291.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].OnClick := ZeroClick;
  2292.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuAxisDiv)].OnClick := nil;
  2293.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewYAxis)].OnClick := NewYAxisClick;
  2294.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].OnClick := EditAxisClick;
  2295.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].OnClick := DeleteAxisClick;
  2296.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFontDiv)].OnClick := nil;
  2297.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewNote)].OnClick := NewNoteClick;
  2298.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].OnClick := MoveNotePointerClick;
  2299.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].OnClick := DeleteNoteClick;
  2300.  
  2301.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].OnClick := EditFontClick;
  2302.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPropertiesDiv)].OnClick := nil;
  2303.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuProperties)].OnClick := EditPropertiesClick;
  2304.  
  2305.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].OnClick := HideClick;
  2306.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuShowAll)].OnClick := ShowAllClick;
  2307.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuDisplayMode)].OnClick := ModeClick;
  2308.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].OnClick := LegendClick;
  2309.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomDiv)].OnClick := nil;
  2310.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuSetAsNormal)].OnClick := SetAsNormalClick;
  2311.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].OnClick := NormalViewClick;
  2312.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuManualZoom)].OnClick := ManualZoomClick;
  2313.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomIn)].OnClick := ZoomInClick;
  2314.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomOut)].OnClick := ZoomOutClick;
  2315.  
  2316.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuPosition)].OnClick := PositionClick;
  2317.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].OnClick := NearestPointClick;
  2318.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].OnClick := nil;
  2319.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].OnClick := AverageClick;
  2320.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].OnClick := CompressSeriesClick;
  2321.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].OnClick := CompressAllSeriesClick;
  2322.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].OnClick := ContractSeriesClick;
  2323.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].OnClick := ContractAllSeriesClick;
  2324.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].OnClick := HighsClick;
  2325.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].OnClick := MovingAverageClick;
  2326.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSpline)].OnClick := SplineClick;
  2327.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].OnClick := SmoothSeriesClick;
  2328.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].OnClick := SortClick;
  2329.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].OnClick := nil;
  2330.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].OnClick := DifferentiateClick;
  2331.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].OnClick := IntegrateClick;
  2332.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].OnClick := IntegralClick;
  2333.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].OnClick := nil;
  2334.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].OnClick := LineBestFitClick;
  2335.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].OnClick := TwoRegionLineBestFitClick;
  2336. {$IFDEF FUNCTIONS}
  2337.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].OnClick := nil;
  2338.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].OnClick := FunctionClick;
  2339. {$ENDIF}
  2340.  
  2341. {$IFDEF FINANCE}
  2342.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuADL)].OnClick := ADLClick;
  2343.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuAroon)].OnClick := ADLClick;
  2344.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuADX)].OnClick := ADLClick;
  2345.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuATR)].OnClick := ADLClick;
  2346.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuBB)].OnClick := ADLClick;
  2347.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuCCI)].OnClick := ADLClick;
  2348.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuCMF)].OnClick := ADLClick;
  2349.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuMACD)].OnClick := ADLClick;
  2350.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuMA)].OnClick := ADLClick;
  2351.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPVO)].OnClick := ADLClick;
  2352.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPO)].OnClick := ADLClick;
  2353.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPR)].OnClick := ADLClick;
  2354.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPVB)].OnClick := ADLClick;
  2355.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuRSI)].OnClick := ADLClick;
  2356.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuStochOsc)].OnClick := ADLClick;
  2357.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuStochRSI)].OnClick := ADLClick;
  2358.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuTRIN)].OnClick := ADLClick;
  2359.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuWilliams)].OnClick := ADLClick;
  2360. {$ENDIF}
  2361.   end;
  2362.  
  2363.   procedure CreateCaptions;
  2364.   begin
  2365.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuNew)].Caption := sNew;
  2366.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOpen)].Caption := sOpen;
  2367.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlayDiv)].Caption := '-';
  2368.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlay)].Caption := sOverlay;
  2369.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuClearOverlays)].Caption := sClearOverlays;
  2370.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveDiv)].Caption := '-';
  2371.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSave)].Caption := sSave;
  2372.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveAs)].Caption := sSaveAs;
  2373.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveImage)].Caption := sSaveImage;
  2374.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrintDiv)].Caption := '-';
  2375.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrint)].Caption := sPrint;
  2376.  
  2377.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopy)].Caption := sCopy;
  2378.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].Caption := sCopyHTML;
  2379.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].Caption := sCopySeries;
  2380.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].Caption := sPaste;
  2381.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].Caption := '-';
  2382.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Caption := sDisplace;
  2383.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].Caption := sResetDisplacement;
  2384.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].Caption := '-';
  2385.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewSeries)].Caption := sNewSeries;
  2386.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].Caption := sCloneSeries;
  2387.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].Caption := sEditPoint;
  2388.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].Caption := sEditData;
  2389.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Caption := sEditSeries;
  2390.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].Caption := sDeleteSeries;
  2391.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].Caption := sLinearize;
  2392.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].Caption := sZero;
  2393.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuAxisDiv)].Caption := '-';
  2394.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewYAxis)].Caption := sNewYAxis;
  2395.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].Caption := sEditAxis;
  2396.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].Caption := sDeleteY2Axis;
  2397.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFontDiv)].Caption := '-';
  2398.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewNote)].Caption := sNewNote;
  2399.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Caption := sMoveNotePointer;
  2400.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Caption := sDeleteNote;
  2401.  
  2402.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Caption := sEditFont;
  2403.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPropertiesDiv)].Caption := '-';
  2404.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuProperties)].Caption := sProperties;
  2405.  
  2406.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Caption := sHide;
  2407.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuShowAll)].Caption := sShowAll;
  2408.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuDisplayModeDiv)].Caption := '-';
  2409.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuDisplayMode)].Caption := sDisplayMode;
  2410.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Caption := sLegend;
  2411.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomDiv)].Caption := '-';
  2412.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuSetAsNormal)].Caption := sSetAsNormal;
  2413.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].Caption := sNormal;
  2414.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuManualZoom)].Caption := sManualZoom;
  2415.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomIn)].Caption := sZoomIn;
  2416.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomOut)].Caption := sZoomOut;
  2417.  
  2418.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuPosition)].Caption := sPosition;
  2419.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].Caption := sNearestPoint;
  2420.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].Caption := '-';
  2421.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Caption := sAverage;
  2422.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Caption := sCompressSeries;
  2423.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].Caption := sCompressAllSeries;
  2424.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].Caption := sContractSeries;
  2425.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].Caption := sContractAllSeries;
  2426.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].Caption := sHighs;
  2427.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].Caption := sMovingAverage;
  2428.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSpline)].Caption := sCubicSpline;
  2429.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].Caption := sSmoothSeries;
  2430.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].Caption := sSortSeries;
  2431.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].Caption := '-';
  2432.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].Caption := sDifferentiate;
  2433.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].Caption := sIntegrate;
  2434.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].Caption := sIntegral;
  2435.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].Caption := '-';
  2436.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Caption := sLineOfBestFit;
  2437.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].Caption := sTwoRegionLineOfBestFit;
  2438. {$IFDEF FUNCTIONS}
  2439.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].Caption := '-';
  2440.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].Caption := sFunction;
  2441. {$ENDIF}
  2442.  
  2443. {$IFDEF FINANCE}
  2444.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuADL)].Caption := sADL;
  2445.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuAroon)].Caption := sAroon;
  2446.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuADX)].Caption := sADX;
  2447.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuATR)].Caption := sATR;
  2448.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuBB)].Caption := sBB;
  2449.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuCCI)].Caption := sCCI;
  2450.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuCMF)].Caption := sCMF;
  2451.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuMACD)].Caption := sMACD;
  2452.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuMA)].Caption := sMA;
  2453.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPVO)].Caption := sPVO;
  2454.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPO)].Caption := sPO;
  2455.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPR)].Caption := sPR;
  2456.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPVB)].Caption := sPVB;
  2457.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuRSI)].Caption := sRSI;
  2458.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuStochOsc)].Caption := sStochOsc;
  2459.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuStochRSI)].Caption := sStochRSI;
  2460.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuTRIN)].Caption := sTRIN;
  2461.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuWilliams)].Caption := sWilliamsR;
  2462. {$ENDIF}
  2463.   end;
  2464.  
  2465.   procedure CreateHints;
  2466.   begin
  2467.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuNew)].Hint := sNewHint;
  2468.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOpen)].Hint := sOpenHint;
  2469.     //FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlayDiv)].Hint := nil;
  2470.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuOverlay)].Hint := sOverlayHint;
  2471.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuClearOverlays)].Hint := sClearOverlaysHint;
  2472.     //FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveDiv)].Hint := nil;
  2473.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSave)].Hint := sSaveHint;
  2474.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveAs)].Hint := sSaveAsHint;
  2475.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveImage)].Hint := sSaveImageHint;
  2476.     //FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrintDiv)].Hint := nil;
  2477.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuPrint)].Hint := sPrintHint;
  2478.  
  2479.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopy)].Hint := sCopyHint;
  2480.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].Hint := sCopyHTMLHint;
  2481.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].Hint := sCopySeriesHint;
  2482.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].Hint := sPasteHint;
  2483.     //FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].Hint := nil;
  2484.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Hint := sDisplaceHint;
  2485.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].Hint := sResetDisplacementHint;
  2486.     //FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].Hint := nil;
  2487.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewSeries)].Hint := sNewSeriesHint;
  2488.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].Hint := sCloneSeriesHint;
  2489.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].Hint := sEditPointHint;
  2490.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].Hint := sEditDataHint;
  2491.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Hint := sEditSeriesHint;
  2492.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].Hint := sDeleteSeriesHint;
  2493.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].Hint := sLinearizeHint;
  2494.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].Hint := sZeroHint;
  2495.     //FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuAxisDiv)].Hint := nil;
  2496.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewYAxis)].Hint := sNewYAxisHint;
  2497.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].Hint := sEditAxisHint;
  2498.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].Hint := sDeleteY2AxisHint;
  2499.     //FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFontDiv)].Hint := nil;
  2500.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuNewNote)].Hint := sNewNoteHint;
  2501.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Hint := sMoveNotePointerHint;
  2502.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Hint := sDeleteNoteHint;
  2503.  
  2504.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Hint := sEditFontHint;
  2505.     //FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPropertiesDiv)].Hint := nil;
  2506.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuProperties)].Hint := sPropertiesHint;
  2507.  
  2508.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Hint := sHideHint;
  2509.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuShowAll)].Hint := sShowAllHint;
  2510.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuDisplayMode)].Hint := sDisplayModeHint;
  2511.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Hint := sLegendHint;
  2512.     //FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomDiv)].Hint := nil;
  2513.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuSetAsNormal)].Hint := sSetAsNormalHint;
  2514.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].Hint := sNormalHint;
  2515.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuManualZoom)].Hint := sManualZoomHint;
  2516.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomIn)].Hint := sZoomInHint;
  2517.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuZoomOut)].Hint := sZoomOutHint;
  2518.  
  2519.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuPosition)].Hint := sPositionHint;
  2520.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].Hint := sNearestPointHint;
  2521.     //FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].Hint := nil;
  2522.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Hint := sAverageHint;
  2523.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Hint := sCompressSeriesHint;
  2524.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].Hint := sCompressAllSeriesHint;
  2525.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].Hint := sContractSeriesHint;
  2526.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].Hint := sContractAllSeriesHint;
  2527.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].Hint := sHighsHint;
  2528.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].Hint := sMovingAverageHint;
  2529.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSpline)].Hint := sCubicSplineHint;
  2530.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].Hint := sSmoothSeriesHint;
  2531.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].Hint := sSortSeriesHint;
  2532.     //FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].Hint := nil;
  2533.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].Hint := sDifferentiateHint;
  2534.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].Hint := sIntegrateHint;
  2535.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].Hint := sIntegralHint;
  2536.     //FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].Hint := nil;
  2537.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Hint := sLineOfBestFitHint;
  2538.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].Hint := sTwoRegionLineOfBestFitHint;
  2539. {$IFDEF FUNCTIONS}
  2540.     //FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].Hint := nil;
  2541.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].Hint := sFunctionHint;
  2542. {$ENDIF}
  2543.  
  2544. {$IFDEF FINANCE}
  2545.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuADL)].Hint := sADLHint;
  2546.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuAroon)].Hint := sAroonHint;
  2547.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuADX)].Hint := sADXHint;
  2548.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuATR)].Hint := sATRHint;
  2549.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuBB)].Hint := sBBHint;
  2550.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuCCI)].Hint := sCCIHint;
  2551.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuCMF)].Hint := sCMFHint;
  2552.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuMACD)].Hint := sMACDHint;
  2553.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuMA)].Hint := sMAHint;
  2554.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPVO)].Hint := sPVOHint;
  2555.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPO)].Hint := sPOHint;
  2556.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPR)].Hint := sPRHint;
  2557.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuPVB)].Hint := sPVBHint;
  2558.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuRSI)].Hint := sRSIHint;
  2559.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuStochOsc)].Hint := sStochOscHint;
  2560.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuStochRSI)].Hint := sStochRSIHint;
  2561.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuTRIN)].Hint := sTRINHint;
  2562.     FPlotPopUpMenu.Items[Ord(mnuFinance)].Items[Ord(mnuWilliams)].Hint := sWilliamsRHint;
  2563. {$ENDIF}
  2564.   end;
  2565.  
  2566. begin
  2567. {create the sub-menus:}
  2568.   TagIndex := 1;
  2569.   CreateTempMenu(0, sFile);
  2570.   CreateTempMenu(1, sEdit);
  2571.   CreateTempMenu(2, sView);
  2572.   CreateTempMenu(3, sCalc);
  2573. {$IFDEF FINANCE}
  2574.   CreateTempMenu(4, sFinance);
  2575. {$ENDIF}
  2576.  
  2577. {create the menus in each sub-menu:}
  2578.   for i := Ord(mnuFile) to MaxIndex do
  2579.   begin
  2580.     for j := 0 to NoMenusItems[i] do
  2581.     begin
  2582.       TempMenuItem := TMenuItem.Create(Self);
  2583.       TempMenuItem.Tag := TagIndex + TAG_BASE;
  2584.  
  2585. {add the TempMenuItem to the popup:}
  2586.       FPlotPopUpMenu.Items[i].Add(TempMenuItem);
  2587.  
  2588.       Inc(TagIndex);
  2589.     end; {j over menu items}
  2590. {remove the temporary menu array used to create the submenu:}
  2591.     if (FPlotPopUpMenu.Items[i].Items[0].Tag = 0) then
  2592.     begin
  2593.       FPlotPopUpMenu.Items[i].Remove(TempMenu[i][0]);
  2594. {then free it:}
  2595.       TempMenu[i][0].Free;
  2596.     end;
  2597.   end; {i over submenus}
  2598.  
  2599. {now set all the OnClick event handlers, Captions and Hints. What a bitch !}
  2600.   CreateOnClicks;
  2601.   CreateCaptions;
  2602.   CreateHints;
  2603.  
  2604. {$IFNDEF SHOWALLMENUS}
  2605.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].Enabled := FALSE;
  2606. {$ENDIF}
  2607.  
  2608. {$IFDEF COMPILER4_UP}
  2609.   ImageIndex := 0;
  2610.   for i := Ord(mnuFile) to Ord(mnuCalc) do //MaxIndex
  2611.   begin
  2612.     for j := 0 to NoMenusItems[i] do
  2613.     begin
  2614.       if (FPlotPopUpMenu.Items[i].Items[j].Caption <> '-') then
  2615.       begin
  2616.         FPlotPopUpMenu.Items[i].Items[j].ImageIndex := ImageIndex;
  2617.         Inc(ImageIndex);
  2618.       end; {not a line}
  2619.     end; {NoMenusItems}
  2620.   end; {SubMenus}
  2621.  
  2622.   {$IFDEF FINANCE}
  2623. {If FUNCTIONS are NOT defined, then we need to skip over the Function bitmap resource:}
  2624.     {$IFNDEF FUNCTIONS}
  2625.   Inc(ImageIndex);
  2626.     {$ENDIF}
  2627.   for j := 0 to NoMenusItems[MaxIndex] do
  2628.   begin
  2629.     if (FPlotPopUpMenu.Items[MaxIndex].Items[j].Caption <> '-') then
  2630.     begin
  2631.       FPlotPopUpMenu.Items[MaxIndex].Items[j].ImageIndex := ImageIndex;
  2632.       //Inc(ImageIndex);
  2633.     end; {not a line}
  2634.   end; {NoMenusItems}
  2635.   {$ENDIF}
  2636. {$ENDIF}  //COMPILER4_UP
  2637.  
  2638. {We create the "which" popup menu:}
  2639.   WhichPopUpMenu := TPopUpMenu.Create(Self);
  2640.   for i := 0 to 1 do begin
  2641.     WhichPopUpItems[i] := TMenuItem.Create(Self);
  2642.     WhichPopUpItems[i].Tag := i;
  2643.     WhichPopUpMenu.Items.Add(WhichPopUpItems[i]);
  2644.   end;
  2645. {Note: we set the FInstructions just before we display this popup:}
  2646.   {WhichPopUpItems[0].Caption := 'ClickedObjectType';}
  2647.   {WhichPopUpItems[1].Caption := 'SecondClickedObjectType';}
  2648.   WhichPopUpItems[0].OnClick := MoveTheClickedObjectClick;
  2649.   WhichPopUpItems[1].OnClick := MoveSecondClickedObjectClick;
  2650.  
  2651. {We create the "Right Drag" popup menu:}
  2652.   RightDragItems[0] :=  Point(Ord(mnuView), Ord(mnuZoomIn));
  2653.   RightDragItems[1] :=  Point(Ord(mnuEdit), Ord(mnuLinearize));
  2654.   RightDragItems[2] :=  Point(Ord(mnuEdit), Ord(mnuZero));
  2655.   RightDragItems[3] :=  Point(Ord(mnuCalc), Ord(mnuCalcAverage));
  2656.   RightDragItems[4] :=  Point(Ord(mnuCalc), Ord(mnuContractSeries));
  2657.   RightDragItems[5] :=  Point(Ord(mnuCalc), Ord(mnuContractAllSeries));
  2658.   RightDragItems[6] :=  Point(Ord(mnuCalc), Ord(mnuIntegral));
  2659.   RightDragItems[7] :=  Point(Ord(mnuCalc), Ord(mnuLineOfBestFit));
  2660.   RightDragItems[8] :=  Point(Ord(mnuCalc), Ord(mnuTwoRegionLineOfBestFit));
  2661.  
  2662.   FDragPopUpMenu := TPopupMenu.Create(Self);
  2663.   for i := 0 to 8 do
  2664.   begin
  2665.     TempMenuItem := TMenuItem.Create(Self);
  2666.     TempMenuItem.Caption :=
  2667.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].Caption;
  2668. {$IFDEF COMPILER4_UP}
  2669.     TempMenuItem.ImageIndex :=
  2670.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].ImageIndex;
  2671. {$ENDIF}
  2672.     TempMenuItem.Tag :=
  2673.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].Tag;
  2674.     TempMenuItem.OnClick :=
  2675.       FPlotPopUpMenu.Items[RightDragItems[i].x].Items[RightDragItems[i].y].OnClick;
  2676.     FDragPopUpMenu.Items.Add(TempMenuItem);
  2677.   end;
  2678. end;
  2679.  
  2680. {------------------------------------------------------------------------------
  2681.     Procedure: TCustomPlot.CreatePageButtons
  2682.   Description: creates the Page buttons and assigns their properties
  2683.        Author: Mat Ballard
  2684.  Date created: 04/28/2001
  2685. Date modified: 04/28/2001 by Mat Ballard
  2686.       Purpose: user interface management
  2687.  Known Issues:
  2688.  ------------------------------------------------------------------------------}
  2689. procedure TCustomPlot.CreatePageButtons;
  2690. var
  2691.   i: Integer;
  2692. begin
  2693.   if (FPageButtons[0] = nil) then
  2694.   begin
  2695.     for i := 0 to 3 do
  2696.     begin
  2697.       FPageButtons[i] := TBitmap.Create;
  2698.     end;
  2699.     FPageButtons[0].LoadFromResourceName(HInstance, 'BMLEFT');
  2700.     FPageButtons[1].LoadFromResourceName(HInstance, 'BMRIGHT');
  2701.     FPageButtons[2].LoadFromResourceName(HInstance, 'BMUP');
  2702.     FPageButtons[3].LoadFromResourceName(HInstance, 'BMDOWN');
  2703.   end;
  2704. end;
  2705.  
  2706. {------------------------------------------------------------------------------
  2707.     Procedure: TCustomPlot.DestroyPageButtons
  2708.   Description: frees the Page buttons
  2709.        Author: Mat Ballard
  2710.  Date created: 04/28/2001
  2711. Date modified: 04/28/2001 by Mat Ballard
  2712.       Purpose: user interface management
  2713.  Known Issues:
  2714.  ------------------------------------------------------------------------------}
  2715. procedure TCustomPlot.DestroyPageButtons;
  2716. var
  2717.   i: Integer;
  2718. begin
  2719.   if (FPageButtons[0] <> nil) then
  2720.   begin
  2721.     for i := 0 to 3 do
  2722.     begin
  2723.       FPageButtons[i].Free;
  2724.       FPageButtons[i] := nil;
  2725.     end;
  2726.   end;
  2727. end;
  2728.  
  2729. {------------------------------------------------------------------------------
  2730.     Procedure: TCustomPlot.PageButtonClick
  2731.   Description: changes the ranges of the axes in Zoomed mode
  2732.        Author: Mat Ballard
  2733.  Date created: 04/28/2001
  2734. Date modified: 04/28/2001 by Mat Ballard
  2735.       Purpose: User Interface control of axis ranges and zooming
  2736.  Known Issues:
  2737.  ------------------------------------------------------------------------------}
  2738. procedure TCustomPlot.PageButtonClick(Index: Integer);
  2739. var
  2740.   Gap,
  2741.   OldVar,
  2742.   NewVar,
  2743.   MinMax: Single;
  2744. begin
  2745.   case Index of
  2746.     0: {left}
  2747.       begin
  2748.         Gap := FXAxis.Max - FXAxis.Min;
  2749.         OldVar := FXAxis.Min;
  2750.         NewVar := OldVar - Gap;
  2751.         MinMax := FSeriesList.Xmin;
  2752.         if (NewVar < MinMax) then
  2753.           NewVar := MinMax;
  2754.         FXAxis.Min := NewVar;
  2755.         FXAxis.Max := NewVar + Gap;
  2756.       end;
  2757.     1: {right}
  2758.       begin
  2759.         Gap := FXAxis.Max - FXAxis.Min;
  2760.         OldVar := FXAxis.Max;
  2761.         NewVar := OldVar + Gap;
  2762.         MinMax := FSeriesList.Xmax;
  2763.         if (NewVar > MinMax) then
  2764.           NewVar := MinMax;
  2765.         FXAxis.Max := NewVar;
  2766.         FXAxis.Min := NewVar - Gap;
  2767.       end;
  2768.     2: {up}
  2769.       begin
  2770.         Gap := FYAxis.Max - FYAxis.Min;
  2771.         OldVar := FYAxis.Max;
  2772.         NewVar := OldVar + Gap;
  2773.         MinMax := FSeriesList.Ymax;
  2774.         if (NewVar > MinMax) then
  2775.           NewVar := MinMax;
  2776.         FYAxis.Max := NewVar;
  2777.         FYAxis.Min := NewVar - Gap;
  2778.       end;
  2779.     3: {down}
  2780.       begin
  2781.         Gap := FYAxis.Max - FYAxis.Min;
  2782.         OldVar := FYAxis.Min;
  2783.         NewVar := OldVar - Gap;
  2784.         MinMax := FSeriesList.Ymin;
  2785.         if (NewVar < MinMax) then
  2786.           NewVar := MinMax;
  2787.         FYAxis.Min := NewVar;
  2788.         FYAxis.Max := NewVar + Gap;
  2789.       end;
  2790.   end;
  2791. end;
  2792.  
  2793. {------------------------------------------------------------------------------
  2794.     Procedure: TCustomPlot.Destroy
  2795.   Description: standard destructor
  2796.        Author: Mat Ballard
  2797.  Date created: 12/1/1999
  2798. Date modified: 02/25/2000 by Mat Ballard
  2799.       Purpose: free sub-components
  2800.  Known Issues:
  2801.  ------------------------------------------------------------------------------}
  2802. Destructor TCustomPlot.Destroy;
  2803. var
  2804.   i: Integer;
  2805. begin
  2806. {nil out the events:}
  2807.   FOnStyleChange := nil;
  2808.   FOnFileOpen := nil;
  2809.   FOnFileClose := nil;
  2810.   FOnHeader := nil;
  2811.   FOnHeaderRequest := nil;
  2812.   FOnHTMLHeaderRequest := nil;
  2813.   FOnSelection := nil;
  2814.   FOnDualSelection := nil;
  2815.  
  2816. {Clear the SeriesList, thereby provoking a file save if required:}
  2817.   Clear(FALSE);
  2818.  
  2819.   DestroyPageButtons;
  2820.  
  2821. {Free all the Notes:}
  2822.   for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  2823.     if (TObject(ScreenObjectList.Items[i]) is TNote) then
  2824.       TNote(ScreenObjectList.Items[i]).Free;
  2825.  
  2826. {Free all the Axes:}
  2827.   for i := FAxisList.Count-1 downto 0 do
  2828.     TAxis(FAxisList.Items[i]).Free;
  2829.  
  2830. {Free the lists of objects:}
  2831.   FAxisList.Free;
  2832.   //NoteList.Free;
  2833.   ScreenObjectList.Free;
  2834.   FSeriesList.Free;
  2835.  
  2836. {Free the visual sub-components}
  2837.   FInstructions.Free;
  2838.   FResult.Free;
  2839.   FLegend.Free;
  2840.   FTitle.Free;
  2841.   FBorder.Free;
  2842.  
  2843. {free non-visible screen elements:}
  2844.   LeftBorder.Free;
  2845.   TopBorder.Free;
  2846.   RightBorder.Free;
  2847.   BottomBorder.Free;
  2848.   Selection.Free;
  2849.  
  2850. {Free fonts, pens, etc:}
  2851.   FHighFont.Free;
  2852.   FMultiplePen.Free;
  2853.   MouseTimer.Free;
  2854.  
  2855. {Free menus:}
  2856.   FPopupOptions.Free;
  2857.   FPlotPopUpMenu.Free;
  2858.   FDragPopUpMenu.Free;
  2859.   WhichPopUpMenu.Free;
  2860.  
  2861. {then call ancestor:}
  2862.   inherited Destroy;
  2863. end;
  2864.  
  2865. {End Constructor and Destructor: ----------------------------------------------}
  2866.  
  2867. {Get functions ----------------------------------------------------------------}
  2868. {------------------------------------------------------------------------------
  2869.      Function: TCustomPlot.GetSeries
  2870.   Description: private property Get function
  2871.        Author: Mat Ballard
  2872.  Date created: 12/1/1999
  2873. Date modified: 02/25/2000 by Mat Ballard
  2874.       Purpose: interface to Series property, which is the default property
  2875.  Known Issues:
  2876.  ------------------------------------------------------------------------------}
  2877. function TCustomPlot.GetSeries(
  2878.   Index: Integer): TSeries;
  2879. begin
  2880.   if ((Index < 0) or (Index >= FSeriesList.Count)) then raise
  2881.     ERangeError.CreateFmt(sGetSeries1, [Index, FSeriesList.Count-1]);
  2882.   GetSeries := TSeries(FSeriesList.Items[Index]);
  2883. end;
  2884.  
  2885. {Set procedures ---------------------------------------------------------------}
  2886. {------------------------------------------------------------------------------
  2887.     Procedure: TCustomPlot.SetAxisDimensions
  2888.   Description: geometry manager
  2889.        Author: Mat Ballard
  2890.  Date created: 12/1/1999
  2891. Date modified: 02/25/2000 by Mat Ballard
  2892.       Purpose: sets up the border, axes and Title position
  2893.  Known Issues:
  2894.  ------------------------------------------------------------------------------}
  2895. procedure TCustomPlot.SetAxisDimensions;
  2896. var
  2897.   i: Integer;
  2898.   TheRect: TRect;
  2899.   pThisYAxis: TAxis;
  2900.   OldIgnoreChanges: Boolean;
  2901.  
  2902.   procedure LimitXAxis;
  2903.   begin
  2904.     if (FXAxis.Intercept < FYAxis.Min) then
  2905.       FXAxis.Intercept := FYAxis.Min;
  2906.     if (FXAxis.Intercept > FYAxis.Max) then
  2907.       FXAxis.Intercept := FYAxis.Max;
  2908.   end;
  2909.  
  2910.   procedure LimitYAxis;
  2911.   begin
  2912.     if (FYAxis.Intercept < FXAxis.Min) then
  2913.       FYAxis.Intercept := FXAxis.Min;
  2914.     if (FYAxis.Intercept > FXAxis.Max) then
  2915.       FYAxis.Intercept := FXAxis.Max;
  2916.   end;
  2917.  
  2918.   procedure LimitZAxis;
  2919.   begin
  2920. {Intercept on the X Axis:}
  2921.     if (FZAxis.Intercept < FXAxis.Min) then
  2922.       FZAxis.Intercept := FXAxis.Min;
  2923.     if (FZAxis.Intercept > FXAxis.Max) then
  2924.       FZAxis.Intercept := FXAxis.Max;
  2925. {Intercept on the Y Axis:}
  2926.     if (FZAxis.ZInterceptY < FYAxis.Min) then
  2927.       FZAxis.ZInterceptY := FYAxis.Min;
  2928.     if (FZAxis.ZInterceptY > FYAxis.Max) then
  2929.       FZAxis.ZInterceptY := FYAxis.Max;
  2930.   end;
  2931.  
  2932. begin
  2933.   OldIgnoreChanges := IgnoreChanges;
  2934.   IgnoreChanges := TRUE;
  2935.  
  2936.   if ((FPlotType = ptContour) or
  2937.       (FPlotType = ptLineContour)) then
  2938.   begin
  2939.     if (FYAxis.AutoScale) then
  2940.     begin
  2941.       FYAxis.Min := FSeriesList.ZMin;
  2942.       FYAxis.Max := FSeriesList.ZMax;
  2943.     end;
  2944.   end;
  2945.  
  2946. {do the simple bits, where the border sets the axis lengths:}
  2947.   FXAxis.Left := FBorder.Left;
  2948.   FXAxis.Right := FBorder.Right;
  2949.   for i := 1 to FAxisList.Count-1 do
  2950.   begin
  2951.     pThisYAxis := TAxis(FAxisList[i]);
  2952.     if (pThisYAxis <> FZAxis) then
  2953.     begin
  2954.       pThisYAxis.Top := FBorder.Top;
  2955.       pThisYAxis.Bottom := FBorder.Bottom;
  2956.     end;
  2957.   end;
  2958.  
  2959. {Limit the X Axis intercept:}
  2960.   LimitXAxis;
  2961.   if (FXAxis.AutoZero) then
  2962.     if ((FYAxis.Min <= 0) and (0 <= FYAxis.Max)) then
  2963.       FXAxis.Intercept := 0;
  2964.  
  2965. {Limit the Y Axis intercept:}
  2966.   LimitYAxis;
  2967.   if (FYAxis.AutoZero) then
  2968.     if ((FXAxis.Min <= 0) and (0 <= FXAxis.Max)) then
  2969.       FYAxis.Intercept := 0;
  2970.  
  2971. {Limit the secondary Y Axes intercepts:}
  2972.   for i := 2 to FAxisList.Count-1 do
  2973.   begin
  2974.     pThisYAxis := TAxis(FAxisList[i]);
  2975.     if (not pThisYAxis.AutoScale) then {???}
  2976.     begin
  2977.       pThisYAxis.Intercept := FXAxis.Max +
  2978.         (i-2) * Width;
  2979.     end;
  2980.  
  2981.     if (pThisYAxis.AxisType = atTertiary) then
  2982.     begin
  2983.       if (pThisYAxis.Intercept < FXAxis.XofF(1)) then
  2984.         pThisYAxis.Intercept := FXAxis.XofF(1);
  2985.       if (pThisYAxis.Intercept > FXAxis.XofF(Width-2)) then
  2986.         pThisYAxis.Intercept := FXAxis.XofF(Width-2);
  2987.     end
  2988.     else
  2989.     begin
  2990. {and Secondary axis is limited to the borders:}
  2991.       if (pThisYAxis.Intercept < FXAxis.Min) then
  2992.         pThisYAxis.Intercept := FXAxis.Min;
  2993.       if (pThisYAxis.Intercept > FXAxis.Max) then
  2994.         pThisYAxis.Intercept := FXAxis.Max;
  2995.     end;
  2996.   end;
  2997.  
  2998. {Set the screen positions based on the Intercepts:}
  2999.   FXAxis.MidY := FYAxis.FofY(FXAxis.Intercept);
  3000.   for i := 1 to FAxisList.Count-1 do
  3001.   begin
  3002.     pThisYAxis := TAxis(FAxisList[i]);
  3003.     if (pThisYAxis <> FZAxis) then
  3004.       pThisYAxis.MidX := FXAxis.FofX(pThisYAxis.Intercept);
  3005.   end;
  3006.  
  3007.   if (FZAxis <> nil) then
  3008.   begin
  3009. {Limit the Z Axis interceptS:}
  3010.     LimitZAxis;
  3011.     if (FZAxis.AutoZero) then
  3012.       if ((FZAxis.Min <= 0) and (0 <= FZAxis.Max)) then
  3013.         FZAxis.Intercept := 0;
  3014. {Set the screen positions based on the Intercepts:}
  3015.     FZAxis.Left := FXAxis.FofX(FZAxis.Intercept);
  3016.     FZAxis.Top := FYAxis.FofY(FZAxis.ZInterceptY);
  3017.   end;
  3018.  
  3019. {do the borders for click-and-drag purposes:}
  3020.   LeftBorder.Top := FBorder.Top;
  3021.   LeftBorder.Bottom := FBorder.Bottom;
  3022.   LeftBorder.MidX := FBorder.Left;
  3023.  
  3024.   RightBorder.Top := FBorder.Top;
  3025.   RightBorder.Bottom := FBorder.Bottom;
  3026.   RightBorder.MidX := FBorder.Right;
  3027.  
  3028.   TopBorder.Left := FBorder.Left;
  3029.   TopBorder.Right := FBorder.Right;
  3030.   TopBorder.MidY := FBorder.Top;
  3031.  
  3032.   BottomBorder.Left := FBorder.Left;
  3033.   BottomBorder.Right := FBorder.Right;
  3034.   BottomBorder.MidY := FBorder.Bottom;
  3035.  
  3036. {set up the title envelope:}
  3037.   TheRect.Left := FBorder.Left;
  3038.   TheRect.Right := FBorder.Right;
  3039.   TheRect.Top := BevelGap + FTitle.Height;
  3040.   TheRect.Bottom := Height - BevelGap - FTitle.Height;
  3041.   FTitle.Envelope := TheRect;
  3042.  
  3043.   IgnoreChanges := OldIgnoreChanges;
  3044. end;
  3045.  
  3046. {------------------------------------------------------------------------------
  3047.     Procedure: TCustomPlot.SetClickAndDragDelay
  3048.   Description: standard property Set procedure
  3049.        Author: Mat Ballard
  3050.  Date created: 04/25/2000
  3051. Date modified: 04/25/2000 by Mat Ballard
  3052.       Purpose: sets the ClickAndDragDelay Property
  3053.  Known Issues:
  3054.  ------------------------------------------------------------------------------}
  3055. procedure TCustomPlot.SetClickAndDragDelay(Value: Integer);
  3056. begin
  3057.   MouseTimer.Interval := Value;
  3058. end;
  3059.  
  3060. {------------------------------------------------------------------------------
  3061.     Procedure: TCustomPlot.SetBubbleSize
  3062.   Description: private property Set procedure
  3063.        Author: Mat Ballard
  3064.  Date created: 12/1/1999
  3065. Date modified: 02/25/2000 by Mat Ballard
  3066.       Purpose: sets the BubbleSize in ptBubble mode
  3067.  Known Issues:
  3068.  ------------------------------------------------------------------------------}
  3069. procedure TCustomPlot.SetBubbleSize(Value: TPercent);
  3070. begin
  3071.   FBubbleSize := Value;
  3072.   DoStyleChange(Self);
  3073. end;
  3074.  
  3075. {------------------------------------------------------------------------------
  3076.     Procedure: TCustomPlot.SetColumnGap
  3077.   Description: private property Set procedure
  3078.        Author: Mat Ballard
  3079.  Date created: 12/1/1999
  3080. Date modified: 02/25/2000 by Mat Ballard
  3081.       Purpose: sets the Gap between Columns in ptColumn mode
  3082.  Known Issues:
  3083.  ------------------------------------------------------------------------------}
  3084. procedure TCustomPlot.SetColumnGap(Value: TPercent);
  3085. begin
  3086.   FColumnGap := Value;
  3087.   DoStyleChange(Self);
  3088. end;
  3089.  
  3090. {------------------------------------------------------------------------------
  3091.     Procedure: TCustomPlot.SetContourDetail
  3092.   Description: private property Set procedure
  3093.        Author: Mat Ballard
  3094.  Date created: 02/08/2001
  3095. Date modified: 02/08/2001 by Mat Ballard
  3096.       Purpose: sets the granularity of the colour interpolation in a contour graph.
  3097.  Known Issues:
  3098.  ------------------------------------------------------------------------------}
  3099. procedure TCustomPlot.SetContourDetail(Value: TContourDetail);
  3100. begin
  3101.   FContourDetail := Value;
  3102.   DoStyleChange(Self);
  3103. end;
  3104.  
  3105. {------------------------------------------------------------------------------
  3106.     Procedure: TCustomPlot.SetContourInterval
  3107.   Description: private property Set procedure
  3108.        Author: Mat Ballard
  3109.  Date created: 07/15/2001
  3110. Date modified: 07/15/2001 by Mat Ballard
  3111.       Purpose: sets the granularity of the intervals in a contour graph.
  3112.  Known Issues:
  3113.  ------------------------------------------------------------------------------}
  3114. procedure TCustomPlot.SetContourInterval(Value: Single);
  3115. begin
  3116.   FContourInterval := Value;
  3117.   DoStyleChange(Self);
  3118. end;
  3119.  
  3120. {------------------------------------------------------------------------------
  3121.     Procedure: TCustomPlot.SetContourStart
  3122.   Description: private property Set procedure
  3123.        Author: Mat Ballard
  3124.  Date created: 07/15/2001
  3125. Date modified: 07/15/2001 by Mat Ballard
  3126.       Purpose: sets the granularity of the Starts in a contour graph.
  3127.  Known Issues:
  3128.  ------------------------------------------------------------------------------}
  3129. procedure TCustomPlot.SetContourStart(Value: Single);
  3130. begin
  3131.   FContourStart := Value;
  3132.   DoStyleChange(Self);
  3133. end;
  3134.  
  3135. {------------------------------------------------------------------------------
  3136.     Procedure: TCustomPlot.SetContourWireFrame
  3137.   Description: private property Set procedure
  3138.        Author: Mat Ballard
  3139.  Date created: 07/15/2001
  3140. Date modified: 07/15/2001 by Mat Ballard
  3141.       Purpose: sets the presence or absence of a wireframe on the 3D surface 
  3142.  Known Issues:
  3143.  ------------------------------------------------------------------------------}
  3144. procedure TCustomPlot.SetContourWireFrame(Value: Boolean);
  3145. begin
  3146.   FContourWireFrame := Value;
  3147.   DoStyleChange(Self);
  3148. end;
  3149.  
  3150. {------------------------------------------------------------------------------
  3151.     Procedure: TCustomPlot.SetDefaultExtension
  3152.   Description: private 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 DefaultExtension for TPlot files
  3157.  Known Issues:
  3158.  ------------------------------------------------------------------------------}
  3159. procedure TCustomPlot.SetDefaultExtension(
  3160.   Value: String);
  3161. begin
  3162.   FDefaultExtension := Value;
  3163.   FileExtensions[0] := Value;
  3164.   FileTypes :=
  3165. {$IFDEF MSWINDOWS}
  3166.     'Plot ' + sFiles + '*.' + Value
  3167.     + '|Comma Sep Var ' + sFiles + '|*.csv'
  3168.     + '|' + sText + ' ' + sFiles + '|*.txt'
  3169.     + '|' + sAll + ' ' + sFiles + '|*.*';
  3170. {$ENDIF}
  3171. {$IFDEF LINUX}
  3172.     'Plot ' + sFiles + '(*.' + Value +
  3173.     ')|Comma Sep Var ' + sFiles + ' (*.csv)' +
  3174.     '|' + sText + ' ' + sFiles + ' (*.txt)' +
  3175.     '|' + sAll + ' ' + sFiles + ' (*.*)';
  3176. {$ENDIF}
  3177. end;
  3178.  
  3179. {------------------------------------------------------------------------------
  3180.     Procedure: TCustomPlot.SetDisplayMode
  3181.   Description: private property Set procedure
  3182.        Author: Mat Ballard
  3183.  Date created: 12/1/1999
  3184. Date modified: 02/25/2000 by Mat Ballard
  3185.       Purpose: sets the DisplayMode property, which is how
  3186.                graphs are updated when more data is Added
  3187.  Known Issues:
  3188.  ------------------------------------------------------------------------------}
  3189. procedure TCustomPlot.SetDisplayMode(
  3190.   Value: TDisplayMode);
  3191. begin
  3192.   if (FDisplayMode = Value) then exit;
  3193.  
  3194.   SetDisplayModeHistory(FDisplayHistory, Value);
  3195. end;
  3196.  
  3197. {------------------------------------------------------------------------------
  3198.     Procedure: TCustomPlot.SetDisplayModeHistory
  3199.   Description: adjusts axes and sets DisplayMode and History properties
  3200.        Author: Mat Ballard
  3201.  Date created: 12/1/1999
  3202. Date modified: 02/25/2000 by Mat Ballard
  3203.       Purpose: DisplayMode and History must be set and the graph updated simultaneously.
  3204.  Known Issues:
  3205.  ------------------------------------------------------------------------------}
  3206. procedure TCustomPlot.SetDisplayModeHistory(
  3207.   HistoryValue: Single;
  3208.   ScalingValue: TDisplayMode);
  3209. begin
  3210.   if (ScalingValue = dmHistory) then
  3211.   begin
  3212. {we are changing to History from normal behaviour,
  3213.  or we are in History mode:}
  3214.     FXAxis.Min := -HistoryValue;
  3215.     FXAxis.Max := 0;
  3216.     FYAxis.Intercept := -HistoryValue;
  3217.   end
  3218.   else if (FDisplayMode = dmHistory) then
  3219.   begin
  3220. {We are changing from History to normal behaviour.
  3221.  We therefore need to reset the X Axis dimensions:}
  3222.     if (ScalingValue = dmRun) then
  3223.       FXAxis.Max := 1.5 * FSeriesList.Xmax
  3224.     else
  3225.       FXAxis.Max := FSeriesList.Xmax;
  3226.     FXAxis.Min := FSeriesList.Xmin;
  3227.     FYAxis.Intercept := FXAxis.Min;
  3228.   end;
  3229.   FDisplayHistory := HistoryValue;
  3230.   FDisplayMode := ScalingValue;
  3231.   DoStyleChange(Self);
  3232. end;
  3233.  
  3234. {------------------------------------------------------------------------------
  3235.     Procedure: TCustomPlot.SetGrid
  3236.   Description: private property Set procedure
  3237.        Author: Mat Ballard
  3238.  Date created: 02/28/2001
  3239. Date modified: 02/28/2001 by Mat Ballard
  3240.       Purpose: do we want a grid in XY-type graphs ?
  3241.  Known Issues:
  3242.  ------------------------------------------------------------------------------}
  3243. procedure TCustomPlot.SetGrid(Value: TGridType);
  3244. begin
  3245.   if (FGrid = Value) then exit;
  3246.  
  3247.   FGrid := Value;
  3248.   DoStyleChange(Self);
  3249. end;
  3250.  
  3251. {------------------------------------------------------------------------------
  3252.     Procedure: TCustomPlot.SetGridStyle
  3253.   Description: private property Set procedure
  3254.        Author: Mat Ballard
  3255.  Date created: 02/28/2001
  3256. Date modified: 02/28/2001 by Mat Ballard
  3257.       Purpose: do we want a grid in XY-type graphs ?
  3258.  Known Issues:
  3259.  ------------------------------------------------------------------------------}
  3260. procedure TCustomPlot.SetGridStyle(Value: TPenStyle);
  3261. begin
  3262.   if (FGridStyle = Value) then exit;
  3263.  
  3264.   FGridStyle := Value;
  3265.   DoStyleChange(Self);
  3266. end;
  3267.  
  3268. {------------------------------------------------------------------------------
  3269.     Procedure: TCustomPlot.SetGridColor
  3270.   Description: private property Set procedure
  3271.        Author: Mat Ballard
  3272.  Date created: 02/28/2001
  3273. Date modified: 02/28/2001 by Mat Ballard
  3274.       Purpose: do we want a grid in XY-type graphs ?
  3275.  Known Issues:
  3276.  ------------------------------------------------------------------------------}
  3277. procedure TCustomPlot.SetGridColor(Value: TColor);
  3278. begin
  3279.   if (FGridColor = Value) then exit;
  3280.  
  3281.   FGridColor := Value;
  3282.   DoStyleChange(Self);
  3283. end;
  3284.  
  3285. {------------------------------------------------------------------------------
  3286.     Procedure: TCustomPlot.SetWallColor
  3287.   Description: private property Set procedure
  3288.        Author: Mat Ballard
  3289.  Date created: 02/28/2001
  3290. Date modified: 02/28/2001 by Mat Ballard
  3291.       Purpose: do we want a Wall in XY-type graphs ?
  3292.  Known Issues:
  3293.  ------------------------------------------------------------------------------}
  3294. procedure TCustomPlot.SetWallColor(Value: TColor);
  3295. begin
  3296.   if (FWallColor = Value) then exit;
  3297.  
  3298.   FWallColor := Value;
  3299.   DoStyleChange(Self);
  3300. end;
  3301.  
  3302. {------------------------------------------------------------------------------
  3303.     Procedure: TCustomPlot.SetFileName
  3304.   Description: private property Set procedure
  3305.        Author: Mat Ballard
  3306.  Date created: 12/1/1999
  3307. Date modified: 02/25/2000 by Mat Ballard
  3308.       Purpose: sets and parses the FileName property
  3309.  Known Issues:
  3310.  ------------------------------------------------------------------------------}
  3311. procedure TCustomPlot.SetFileName(
  3312.   Value: String);
  3313. begin
  3314.   if (FFileName = Value) then exit;
  3315.  
  3316.   FFileName := Value;
  3317.   if (Length(FFileName) > 0) then
  3318.   begin
  3319.     PropsFileName := GetFileDriveDir;
  3320.     PropsFileName := PropsFileName + GetFileRoot + '.';
  3321.     PropsFileName := PropsFileName + PROP_EXTENSION;
  3322.   end
  3323.    else
  3324.     PropsFileName := '';
  3325. end;
  3326.  
  3327.  
  3328. {------------------------------------------------------------------------------
  3329.     Functions: TCustomPlot.GetFileXXX
  3330.   Description: gets various file parameters from the name
  3331.        Author: Mat Ballard
  3332.  Date created: 08/10/2000
  3333. Date modified: 08/10/2000 by Mat Ballard
  3334.       Purpose: file management
  3335.  Known Issues:
  3336.  ------------------------------------------------------------------------------}
  3337. function TCustomPlot.GetFileExtension: String; {csv}
  3338. var
  3339.   FileExtension: String;
  3340. begin
  3341.   FileExtension := LowerCase(ExtractFileExt(FFileName));
  3342.   if (Pos('.', FileExtension) = 1) then
  3343.     FileExtension := Copy(FileExtension, 2, Length(FileExtension));
  3344.   GetFileExtension := FileExtension;
  3345. end;
  3346.  
  3347. function TCustomPlot.GetFileDriveDir: String;  {D:\Data\Delphi\Plot}
  3348. var
  3349.   FileDriveDir: String;
  3350. begin
  3351.   FileDriveDir := ExtractFilePath(FFileName);
  3352.   if (Length(FileDriveDir) = 0) then
  3353.     FileDriveDir := GetCurrentDir;
  3354.   GetFileDriveDir := FileDriveDir;
  3355. end;
  3356.  
  3357. function TCustomPlot.GetFileRoot: String;      {Test3}
  3358. var
  3359.   Ext,
  3360.   FileRoot: String;
  3361.   i: Integer;
  3362. begin
  3363.   Ext := GetFileExtension;
  3364.   if (Length(Ext) > 0) then
  3365.   begin
  3366.     FileRoot := ExtractFileName(FFileName);
  3367.     i := Pos(Ext, FileRoot);
  3368.     FileRoot := Copy(FileRoot, 1, i-2);
  3369.   end
  3370.   else
  3371.     FileRoot := FFileName;
  3372.   GetFileRoot := FileRoot;
  3373. end;
  3374.  
  3375. {------------------------------------------------------------------------------
  3376.     Procedure: TCustomPlot.GetFilterIndex
  3377.   Description: gets the file filter index from the extension
  3378.        Author: Mat Ballard
  3379.  Date created: 08/10/2000
  3380. Date modified: 08/10/2000 by Mat Ballard
  3381.       Purpose: file management
  3382.  Known Issues:
  3383.  ------------------------------------------------------------------------------}
  3384. function TCustomPlot.GetFilterIndex(
  3385.   Ext: String): Integer;
  3386. var
  3387.   i: Integer;
  3388. begin
  3389. {the default filterindex is actually '*'}
  3390.   GetFilterIndex := 4;
  3391.   for i := 0 to 3 do
  3392.   begin
  3393.     if (LowerCase(Ext) = FileExtensions[i]) then
  3394.     begin
  3395.       GetFilterIndex := i+1;
  3396.       break;
  3397.     end;
  3398.   end;
  3399. end;
  3400. {------------------------------------------------------------------------------
  3401.     Procedure: TCustomPlot.SetHistory
  3402.   Description: private property Set procedure
  3403.        Author: Mat Ballard
  3404.  Date created: 12/1/1999
  3405. Date modified: 02/25/2000 by Mat Ballard
  3406.       Purpose: sets the History property: which is how far back
  3407.                a History graph goes
  3408.  Known Issues:
  3409.  ------------------------------------------------------------------------------}
  3410. procedure TCustomPlot.SetHistory(
  3411.   Value: Single);
  3412. begin
  3413.   if (FDisplayHistory = Value) then exit;
  3414.  
  3415.   SetDisplayModeHistory(Value, FDisplayMode);
  3416. end;
  3417.  
  3418. {------------------------------------------------------------------------------
  3419.     Procedure: TCustomPlot.SetInstructions
  3420.   Description: private property Set procedure
  3421.        Author: Mat Ballard
  3422.  Date created: 10/09/1999
  3423. Date modified: 10/09/2000 by Mat Ballard
  3424.       Purpose: sets the Instructions property
  3425.  Known Issues: Fixed IDE crash when Instructions set
  3426.  ------------------------------------------------------------------------------}
  3427. procedure TCustomPlot.SetInstructions(Value: TStringList);
  3428. begin
  3429.   if (Value.Count > 0) then
  3430.     FInstructions.Assign(Value)
  3431.    else
  3432.     FInstructions.Clear;
  3433.   DoStyleChange(Self);
  3434. end;
  3435.  
  3436. {------------------------------------------------------------------------------
  3437.     Procedure: TCustomPlot.SetInstructions
  3438.   Description: private property Set procedure
  3439.        Author: Mat Ballard
  3440.  Date created: 07/23/2001
  3441. Date modified: 07/23/2001 by Mat Ballard
  3442.       Purpose: sets the Instructions property by its text
  3443.  Known Issues: 
  3444.  ------------------------------------------------------------------------------}
  3445. procedure TCustomPlot.SetInstructionText(Value: String);
  3446. begin
  3447.   FInstructions.Text := Value;
  3448.   DoStyleChange(Self);
  3449. end;
  3450.  
  3451. {$IFDEF COMPILER4_UP}
  3452. {------------------------------------------------------------------------------
  3453.     Procedure: TCustomPlot.SetImages
  3454.   Description: private property Set procedure
  3455.        Author: Mat Ballard
  3456.  Date created: 10/09/1999
  3457. Date modified: 10/09/2000 by Mat Ballard
  3458.       Purpose: sets the Images property
  3459.  Known Issues: TMenu.Images is of type TCustomImageList, which lurks in unit
  3460.                imglist; however, BC++'s DCLSTD35 contains an imglist, and so
  3461.                we get a namespace collision.
  3462.  ------------------------------------------------------------------------------}
  3463. procedure TCustomPlot.SetImages(Value: TImageList);
  3464. begin
  3465.   FPlotPopUpMenu.Images := Value;
  3466.   FDragPopUpMenu.Images := Value;
  3467. end;
  3468.  
  3469. {------------------------------------------------------------------------------
  3470.     Procedure: TCustomPlot.GetImages
  3471.   Description: private property Set procedure
  3472.        Author: Mat Ballard
  3473.  Date created: 10/09/1999
  3474. Date modified: 10/09/2000 by Mat Ballard
  3475.       Purpose: sets the Images property
  3476.  Known Issues: TMenu.Images is of type TCustomImageList, which lurks in unit
  3477.                imglist; however, BC++'s DCLSTD35 contains an imglist, and so
  3478.                we get a namespace collision.
  3479.  ------------------------------------------------------------------------------}
  3480. function TCustomPlot.GetImages: TImageList;
  3481. begin
  3482.   GetImages := TImageList(FPlotPopUpMenu.Images);
  3483. end;
  3484. {$ENDIF}
  3485.  
  3486. {------------------------------------------------------------------------------
  3487.     Procedure: TCustomPlot.SetMetafileDescription
  3488.   Description: sets the CreatedBy and Description properties
  3489.                if they are not yet set
  3490.        Author: Mat Ballard
  3491.  Date created: 12/1/1999
  3492. Date modified: 02/25/2000 by Mat Ballard
  3493.       Purpose: fully utilise enhanced metafile capabilities to
  3494.                put keywords into WMF
  3495.  Known Issues:
  3496.  ------------------------------------------------------------------------------}
  3497. {$IFDEF MSWINDOWS}
  3498.   {$IFDEF COMPILER2_UP}
  3499. procedure TCustomPlot.SetMetafileDescription;
  3500. var
  3501.   i: Integer;
  3502. begin
  3503.   if (Length(FCreatedBy) = 0) then
  3504.     FCreatedBy := 'Chemware';
  3505.   FCreatedBy := InputBox(sAuthor, sCreatedBy2, FCreatedBy);
  3506.  
  3507.   if (Length(FDescription) = 0) then
  3508.   begin
  3509.     FDescription := FTitle.Caption + ': ';
  3510.     for i := 0 to FSeriesList.Count-1 do
  3511.     begin
  3512.       FDescription := FDescription + TSeries(FSeriesList.Items[i]).Name + ', ';
  3513.     end;
  3514. {remove trailing ', ':}
  3515.     SetLength(FDescription, Length(FDescription)-2);
  3516.   end;
  3517.   FDescription := InputBox(sAuthor, sSetMetafileDescription1, FDescription);
  3518. end;
  3519.   {$ENDIF}
  3520. {$ENDIF}
  3521.  
  3522. {------------------------------------------------------------------------------
  3523.     Procedure: TCustomPlot.SetMultiplicity
  3524.   Description: standard property Set procedure
  3525.        Author: Mat Ballard
  3526.  Date created: 12/1/1999
  3527. Date modified: 02/25/2000 by Mat Ballard
  3528.       Purpose: sets the Multiplicity property
  3529.  Known Issues: see also: PlotTpe property
  3530.  ------------------------------------------------------------------------------}
  3531. procedure TCustomPlot.SetMultiplicity(Value: Byte);
  3532. begin
  3533.   FMultiplicity := Value;
  3534.   if (FPlotType = ptMultiple) then DoStyleChange(Self);
  3535. end;
  3536.  
  3537. {------------------------------------------------------------------------------
  3538.     Procedure: TCustomPlot.SetMultiplePen
  3539.   Description: standard property Set procedure
  3540.        Author: Mat Ballard
  3541.  Date created: 12/1/1999
  3542. Date modified: 02/25/2000 by Mat Ballard
  3543.       Purpose: sets the Multiplicity property
  3544.  Known Issues: see also: PlotType property
  3545.  ------------------------------------------------------------------------------}
  3546. procedure TCustomPlot.SetMultiplePen(Value: TPen);
  3547. begin
  3548.   FMultiplePen.Assign(Value);
  3549.   if (FPlotType = ptMultiple) then DoStyleChange(Self);
  3550. end;
  3551.  
  3552. {------------------------------------------------------------------------------
  3553.      Function: TCustomPlot.GetMultiJoin
  3554.   Description: standard property Set procedure
  3555.        Author: Mat Ballard
  3556.  Date created: 04/18/2001
  3557. Date modified: 04/18/2001 by Mat Ballard
  3558.       Purpose: sets the MultiJoin property
  3559.  Return Value: String, in the form "x,y"
  3560.  Known Issues: see also: PlotType property
  3561.  ------------------------------------------------------------------------------}
  3562. function TCustomPlot.GetMultiJoin: String;
  3563. begin
  3564.   GetMultiJoin := Format('%d,%d', [FMultiJoin1, FMultiJoin2]);
  3565. end;
  3566.  
  3567. {------------------------------------------------------------------------------
  3568.     Procedure: TCustomPlot.SetMultiJoin
  3569.   Description: standard property Set procedure
  3570.        Author: Mat Ballard
  3571.  Date created: 04/18/2001
  3572. Date modified: 04/18/2001 by Mat Ballard
  3573.       Purpose: sets the MultiJoin property
  3574.  Known Issues: see also: PlotType property
  3575.  ------------------------------------------------------------------------------}
  3576. procedure TCustomPlot.SetMultiJoin(Value: String);
  3577. var
  3578.   TempStr, TheCell: String;
  3579.   Index: Integer;
  3580. begin
  3581.   if (Value = GetMultiJoin) then exit;
  3582.  
  3583.   if (Pos(',', Value) > 0) then
  3584.   begin
  3585.     TempStr := Value;
  3586.     TheCell := GetWord(TempStr, ',');
  3587. {If any of this throws an exception, we know we have a loser:}
  3588.     try
  3589.       Index := StrToInt(TheCell);
  3590.     {if ((Index < 0) or (Index >= FSeriesList.Count)) then}
  3591.       FMultiJoin2 := StrToInt(TempStr);
  3592.       FMultiJoin1 := Index;
  3593.     except
  3594.       ShowMessage(Value + sSetMultiJoin1 + #10 + #10 +
  3595.         sSetMultiJoin2);
  3596.     end;
  3597.     if (FPlotType = ptMultiple) then DoStyleChange(Self);
  3598.   end;
  3599. end;
  3600.  
  3601. {------------------------------------------------------------------------------
  3602.     Procedure: TCustomPlot.SetPieRowCount
  3603.   Description: standard property Set procedure
  3604.        Author: Mat Ballard
  3605.  Date created: 12/1/1999
  3606. Date modified: 02/25/2000 by Mat Ballard
  3607.       Purpose: sets the PieRowCount property
  3608.  Known Issues:
  3609.  ------------------------------------------------------------------------------}
  3610. procedure TCustomPlot.SetPieRowCount(Value: Byte);
  3611. begin
  3612.   if ((Value > 0) and
  3613.       (Value <= FSeriesList.Count) and
  3614.       (Value <> FPieRowCount)) then
  3615.   begin
  3616.     FPieRowCount := Value;
  3617.     DoStyleChange(Self);
  3618.   end;
  3619. end;
  3620.  
  3621. {------------------------------------------------------------------------------
  3622.     Procedure: TCustomPlot.SetNoSeries
  3623.   Description: standard property Set procedure
  3624.        Author: Mat Ballard
  3625.  Date created: 22/12/2000
  3626. Date modified: 22/12/2000 by Mat Ballard
  3627.       Purpose: sets the NoSeries property
  3628.  Known Issues:
  3629.  ------------------------------------------------------------------------------}
  3630. procedure TCustomPlot.SetNoSeries(Value: Word);
  3631. var
  3632.   i,
  3633.   j: Integer;
  3634. begin
  3635.   if (Value = FSeriesList.Count) then exit;
  3636.  
  3637.   if (Value > FSeriesList.Count) then
  3638.   begin
  3639.     for i := FSeriesList.Count+1 to Value do
  3640.     begin
  3641. {note that the series are added with independent X data:}
  3642.       j := FSeriesList.Add(-1);
  3643.       TSeries(FSeriesList.Items[j]).OnStyleChange := DoStyleChange;
  3644.     end;
  3645.     if (csDesigning in ComponentState) then
  3646.       MakeDummyData(20);
  3647.   end
  3648.   else
  3649.   begin
  3650.     for i := FSeriesList.Count-1 downto Value do
  3651.       DeleteSeries(i);
  3652.   end;
  3653. end;
  3654.  
  3655. {------------------------------------------------------------------------------
  3656.     Procedure: TCustomPlot.SetOutlineWidth
  3657.   Description: standard property Set procedure
  3658.        Author: Mat Ballard
  3659.  Date created: 12/1/1999
  3660. Date modified: 02/25/2000 by Mat Ballard
  3661.       Purpose: sets the OutlineWidth property
  3662.  Known Issues:
  3663.  ------------------------------------------------------------------------------}
  3664. procedure TCustomPlot.SetOutlineWidth(
  3665.   Value: Integer);
  3666. begin
  3667.   if (FOutlineWidth = Value) then exit;
  3668.  
  3669. {Set border widths:}
  3670.   FOutlineWidth := Value;
  3671.   LeftBorder.Height := FOutlineWidth;
  3672.   LeftBorder.Width := FOutlineWidth;
  3673.   TopBorder.Height := FOutlineWidth;
  3674.   TopBorder.Width := FOutlineWidth;
  3675.   RightBorder.Height := FOutlineWidth;
  3676.   RightBorder.Width := FOutlineWidth;
  3677.   BottomBorder.Height := FOutlineWidth;
  3678.   BottomBorder.Width := FOutlineWidth;
  3679.  
  3680. {Set axis widths:}
  3681.   FXAxis.Height := FOutlineWidth;
  3682.   FYAxis.Width := FOutlineWidth;
  3683.  
  3684.   SetAxisDimensions;
  3685. end;
  3686.  
  3687. {------------------------------------------------------------------------------
  3688.     Procedure: TCustomPlot.SetOnSelection
  3689.   Description: standard property Set procedure
  3690.        Author: Mat Ballard
  3691.  Date created: 04/25/2000
  3692. Date modified: 04/25/2000 by Mat Ballard
  3693.       Purpose: sets the OnSelection event
  3694.  Known Issues:
  3695.  ------------------------------------------------------------------------------}
  3696. procedure TCustomPlot.SetOnSelection(Value: TOnSelectionEvent);
  3697. begin
  3698.   FOnSelection := Value;
  3699.   ScreenJob := sjSelection;
  3700. end;
  3701.  
  3702. {------------------------------------------------------------------------------
  3703.     Procedure: TCustomPlot.SetOnDualSelection
  3704.   Description: standard property Set procedure
  3705.        Author: Mat Ballard
  3706.  Date created: 04/25/2000
  3707. Date modified: 04/25/2000 by Mat Ballard
  3708.       Purpose: sets the OnDualSelection event
  3709.  Known Issues:
  3710.  ------------------------------------------------------------------------------}
  3711. procedure TCustomPlot.SetOnDualSelection(Value: TOnDualSelectionEvent);
  3712. begin
  3713.   FOnDualSelection := Value;
  3714.   ScreenJob := sjDualSelection1;
  3715. end;
  3716.  
  3717.  
  3718. {The painting/drawing methods -----------------------------------------------}
  3719. {------------------------------------------------------------------------------
  3720.     Procedure: TCustomPlot.Paint
  3721.   Description: painting the graph
  3722.        Author: Mat Ballard
  3723.  Date created: 12/1/1999
  3724. Date modified: 02/25/2000 by Mat Ballard
  3725.       Purpose: paints the background, border, then draws the graph: NOT called by graphics and printer.
  3726.  Known Issues:
  3727.  ------------------------------------------------------------------------------}
  3728. procedure TCustomPlot.Paint;
  3729. {const
  3730.   Alignments: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER);}
  3731. var
  3732.   iX, iY: Integer;
  3733.   Rect: TRect;
  3734.   TopColor,
  3735.   BottomColor: TColor;
  3736.  
  3737.   procedure AdjustColors(Bevel: TPanelBevel);
  3738.   begin
  3739.     TopColor := clBtnHighlight;
  3740.     if Bevel = bvLowered then TopColor := clBtnShadow;
  3741.     BottomColor := clBtnShadow;
  3742.     if Bevel = bvLowered then BottomColor := clBtnHighlight;
  3743.   end;
  3744.  
  3745. begin
  3746. {$IFDEF DELPHI3_UP}
  3747.   Assert(Canvas <> nil, sPaintError);
  3748. {$ENDIF}
  3749.  
  3750.   if Assigned(FOnBeforePaint) then
  3751.     OnBeforePaint(Self, Canvas);
  3752.  
  3753.   Canvas.Pen.Mode := pmCopy;
  3754.   Canvas.Pen.Style := psSolid;
  3755.  
  3756.   BevelGap := 0;
  3757.   Rect := GetClientRect;
  3758.   if BevelOuter <> bvNone then
  3759.   begin
  3760.     Inc(BevelGap);
  3761.     AdjustColors(BevelOuter);
  3762.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  3763.   end;
  3764.  
  3765.   Frame3D(Canvas, Rect, Color, Color, BorderWidth);
  3766.  
  3767.   if BevelInner <> bvNone then
  3768.   begin
  3769.     Inc(BevelGap);
  3770.     AdjustColors(BevelInner);
  3771.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  3772.   end;
  3773.   BevelGap := BevelGap * BevelWidth;
  3774.  
  3775.   Canvas.Brush.Color := Color;
  3776.   Canvas.FillRect(Rect);
  3777.   Canvas.Brush.Style := bsClear;
  3778.  
  3779.   Draw(Canvas);
  3780.  
  3781.   Canvas.Brush.Color := Color;
  3782.   Canvas.Brush.Style := bsClear;
  3783. {The Instructions are usually an instruction to the user.
  3784.  As such, it does not need to be copied or printed,
  3785.  so it is placed here, rather than in the "Draw" method:}
  3786.   DrawInstructions;
  3787.  
  3788.   if (FPageButtons[0] <> nil) then
  3789.   begin
  3790. {Right:}
  3791.     iX := Self.Width - FPageButtons[1].Width - 1;
  3792.     iY := Self.Height - FPageButtons[1].Height - 1;
  3793.     Canvas.Draw(iX, iY, FPageButtons[1]);
  3794. {Down}
  3795.     iX := iX - FPageButtons[3].Width;
  3796.     Canvas.Draw(iX, iY, FPageButtons[3]);
  3797. {Up}
  3798.     Canvas.Draw(iX, iY - FPageButtons[2].Height, FPageButtons[2]);
  3799. {Left}
  3800.     iX := iX - FPageButtons[0].Width;
  3801.     Canvas.Draw(iX, iY, FPageButtons[0]);
  3802.   end;
  3803.  
  3804.  
  3805.   if Assigned(FOnAfterPaint) then
  3806.     OnAfterPaint(Self, Canvas);
  3807. end;
  3808.  
  3809. {------------------------------------------------------------------------------
  3810.     Procedure: TCustomPlot.DrawInstructions
  3811.   Description: draws the instructions
  3812.        Author: Mat Ballard
  3813.  Date created: 12/1/1999
  3814. Date modified: 02/25/2000 by Mat Ballard
  3815.       Purpose: tell the user what to do
  3816.  Known Issues:
  3817.  ------------------------------------------------------------------------------}
  3818. procedure TCustomPlot.DrawInstructions;
  3819. var
  3820.   FontHeight,
  3821.   iX,
  3822.   iY,
  3823.   i: Integer;
  3824. {$IFDEF LINUX}
  3825.   //ARect: TRect;
  3826. {$ENDIF}       
  3827. begin
  3828. {The Instructions are usually an instruction to the user.
  3829.  As such, it does not need to be copied or printed,
  3830.  so it is placed here, rather than in the "Draw" method:}
  3831.   if (FInstructions.Count > 0) then
  3832.   begin
  3833.     Canvas.Font.Assign(Font);
  3834.     FontHeight := Canvas.TextHeight('Wp');
  3835. {Adjust the Position appropriately:}
  3836.     iX := BevelGap + 5;
  3837.     iY := Height - BevelGap - FontHeight;
  3838. {how many lines ?}
  3839.     for i := FInstructions.Count-1 downto 0 do
  3840.     begin
  3841. {Output the text:}
  3842. {$IFDEF MSWINDOWS}
  3843.       Canvas.TextOut(iX, iY, FInstructions[i]);
  3844. {$ENDIF}
  3845. {$IFDEF LINUX}
  3846.       Canvas.TextOut(iX, iY{ + Abs(Canvas.Font.Height)}, FInstructions[i]);
  3847.       //Canvas.TextRect(ARect, iX, iY, FInstructions[i], TOPLEFT_ALIGN);
  3848. {$ENDIF}
  3849.       Dec(iY, FontHeight);
  3850.     end;
  3851.   end;
  3852. end;
  3853.  
  3854. {------------------------------------------------------------------------------
  3855.     Procedure: TCustomPlot.Draw
  3856.   Description: painting the graph
  3857.        Author: Mat Ballard
  3858.  Date created: 12/1/1999
  3859. Date modified: 02/25/2000 by Mat Ballard
  3860.       Purpose: draws the graph on a canvas: graphics and printers call this procedure directly
  3861.  Known Issues:
  3862.  ------------------------------------------------------------------------------}
  3863. procedure TCustomPlot.Draw(
  3864.   ACanvas: TCanvas);
  3865. var
  3866.   FontHeight,
  3867.   FontWidth,
  3868.   i,
  3869.   iX,
  3870.   iY,
  3871.   SeriesIncrement: Integer;
  3872.   OldIgnoreChanges: Boolean;
  3873. begin
  3874. {$IFDEF DELPHI3_UP}
  3875.   Assert(ACanvas <> nil, sDrawError);
  3876. {$ENDIF}
  3877.   if Assigned(FOnBeforeDraw) then
  3878.     OnBeforeDraw(Self, ACanvas);
  3879.  
  3880.   OldIgnoreChanges := IgnoreChanges;
  3881.   IgnoreChanges := TRUE;
  3882.  
  3883.   FTitle.Draw(ACanvas);
  3884.  
  3885.   if (FResult.Visible) and (Length(FResult.Caption) > 0) then
  3886.   begin
  3887.     ACanvas.Font.Assign(FResult.Font);
  3888.     FontHeight := Abs(ACanvas.Font.Height);
  3889.     FontWidth := ACanvas.TextWidth(FResult.Caption);
  3890. {calculate the caption dimensions:}
  3891.     FResult.Right := FResult.Left + FontWidth;
  3892.     FResult.Bottom := FResult.Top + FontHeight;
  3893. {output text to screen:}
  3894.     ACanvas.TextOut(FResult.Left, FResult.Top, FResult.Caption);
  3895. {now draw the line itself:}
  3896. {Y = Intercept + Slope * X  <=> X = (Y - Intercept) / Slope}
  3897.     ACanvas.Pen.Style := psDot;
  3898.     ACanvas.Pen.Color := Font.Color;
  3899.     iX := FXAxis.FofX(XAxis.Min);
  3900.     iY := FYAxis.FofY(Intercept + Slope * XAxis.Min);
  3901.     if (iY < Border.Top) then
  3902.     begin
  3903.       iY := Border.Top;
  3904.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3905.     end
  3906.     else if (iY > Border.Bottom) then
  3907.     begin
  3908.       iY := Border.Bottom;
  3909.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3910.     end;
  3911.     ACanvas.MoveTo(iX, iY);
  3912.     iX := FXAxis.FofX(XAxis.Max);
  3913.     iY := FYAxis.FofY(Intercept + Slope * XAxis.Max);
  3914.     if (iY < Border.Top) then
  3915.     begin
  3916.       iY := Border.Top;
  3917.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3918.     end
  3919.     else if (iY > Border.Bottom) then
  3920.     begin
  3921.       iY := Border.Bottom;
  3922.       iX := FXAxis.FofX((FYAxis.YofF(iY) - Intercept)/Slope);
  3923.     end;
  3924.     Canvas.LineTo(iX, iY);
  3925.   end; {Result Visible}
  3926.  
  3927.   if (FGrid > gtNone) then
  3928.   begin
  3929.     if (FPlotType <= ptBubble) then
  3930.       DrawGrid(ACanvas);
  3931.     if (FPlotType >= pt3DContour) then
  3932.       DrawWalls(ACanvas);
  3933.   end;
  3934.  
  3935.   FXAxis.Draw(ACanvas, FYAxis.Top);
  3936.   for i := 1 to FAxisList.Count-1 do
  3937.     TAxis(FAxisList[i]).Draw(ACanvas, FXAxis.Right);
  3938.  
  3939.   if ((FPlotType = ptError) or
  3940.       (FPlotType = ptBubble)) then
  3941.     SeriesIncrement := 2
  3942.    else
  3943.     SeriesIncrement := 1;
  3944.   FLegend.Draw(ACanvas, SeriesIncrement);
  3945.  
  3946.   ACanvas.Font.Assign(FHighFont);
  3947.   case FPlotType of
  3948.     ptXY:
  3949.       begin
  3950.         if (FDisplayMode < dmHistory) then
  3951.           FSeriesList.Draw(ACanvas, FXYFastAt)
  3952.          else
  3953.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);
  3954.       end;
  3955.     ptError:
  3956.       begin
  3957.         if (FDisplayMode < dmHistory) then
  3958.           FSeriesList.DrawError(ACanvas);
  3959.       end;
  3960.     ptMultiple:
  3961.       begin
  3962.         if (FDisplayMode < dmHistory) then
  3963.         begin
  3964.           FSeriesList.DrawMultiple(ACanvas,
  3965.             FMultiplicity,
  3966.             FMultiplePen,
  3967.             FMultiJoin1, FMultiJoin2);
  3968.         end
  3969.         else
  3970.         begin
  3971.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);
  3972.           ACanvas.Pen.Assign(FMultiplePen);
  3973.           FSeriesList.DrawHistoryMultiple(ACanvas, FMultiplicity);
  3974.         end;
  3975.       end;
  3976.     ptBubble:
  3977.       begin
  3978.         if (FDisplayMode < dmHistory) then
  3979.           FSeriesList.DrawBubble(ACanvas, FBubbleSize);
  3980.          {else
  3981.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3982.       end;
  3983.     ptColumn:
  3984.       begin
  3985.         if (FDisplayMode < dmHistory) then
  3986.           FSeriesList.DrawColumns(ACanvas, FColumnGap);
  3987.          {else
  3988.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3989.       end;
  3990.     ptStack:
  3991.         if (FDisplayMode < dmHistory) then
  3992.           FSeriesList.DrawStack(ACanvas, FColumnGap);
  3993.          {else
  3994.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  3995.     ptNormStack:
  3996.         if (FDisplayMode < dmHistory) then
  3997.           FSeriesList.DrawNormStack(ACanvas, FColumnGap);
  3998.          {else
  3999.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  4000.     ptPie:
  4001.         if (FDisplayMode < dmHistory) then
  4002.         begin
  4003.           FSeriesList.DrawPie(ACanvas, FBorder, FPieRowCount);
  4004.         end;
  4005.          {else
  4006.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  4007.     ptPolar:
  4008.         if (FDisplayMode < dmHistory) then
  4009.           FSeriesList.DrawPolar(ACanvas, FPolarRange);
  4010.          {else
  4011.           FSeriesList.DrawHistory(ACanvas, FDisplayHistory);}
  4012.     ptLineContour:
  4013.       begin
  4014.         if (FDisplayMode < dmHistory) then
  4015.           FSeriesList.DrawLineContour(ACanvas, FContourStart, FContourInterval, FContourDetail);
  4016.       end;
  4017.     ptContour:
  4018.       begin
  4019.         if (FDisplayMode < dmHistory) then
  4020.           FSeriesList.DrawContour(ACanvas, FContourDetail);
  4021.       end;
  4022.     pt3DContour:
  4023.       begin
  4024.         if (FDisplayMode < dmHistory) then
  4025.           FSeriesList.Draw3DContour(ACanvas, FZAxis, FContourDetail, FContourWireFrame);
  4026.         //DrawContourColors(ACanvas);
  4027.       end;
  4028.     pt3DWire:
  4029.       begin
  4030.         if (FDisplayMode < dmHistory) then
  4031.           FSeriesList.Draw3DWire(ACanvas, FZAxis, FZLink);
  4032.       end;
  4033.     pt3DColumn:
  4034.       begin
  4035.         if (FDisplayMode < dmHistory) then
  4036.           FSeriesList.Draw3DColumn(ACanvas, FZAxis, FColumnGap)
  4037.       end;
  4038.     {pt3DSurface:
  4039.       begin
  4040.         if (FDisplayMode < dmHistory) then
  4041.           FSeriesList.Draw3DSurface(ACanvas, FZAxis);
  4042.       end;}
  4043.   end;
  4044.  
  4045.   for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  4046.   begin
  4047.     if (TObject(ScreenObjectList.Items[i]) is TNote) then
  4048.       TNote(ScreenObjectList.Items[i]).Draw(ACanvas);
  4049.   end;
  4050.  
  4051.  
  4052.   if Assigned(FOnAfterDraw) then
  4053.     OnAfterDraw(Self, ACanvas);
  4054.  
  4055.   IgnoreChanges := OldIgnoreChanges;
  4056. end;
  4057.  
  4058. {------------------------------------------------------------------------------
  4059.     Procedure: TCustomPlot.DrawGrid
  4060.   Description: painting the graph
  4061.        Author: Mat Ballard
  4062.  Date created: 12/1/1999
  4063. Date modified: 02/25/2000 by Mat Ballard
  4064.       Purpose: draws the grid for xy-type plots
  4065.      Comments:  
  4066.  Known Issues:
  4067.  ------------------------------------------------------------------------------}
  4068. procedure TCustomPlot.DrawGrid(
  4069.   ACanvas: TCanvas);
  4070. var
  4071.   iX, iY: Integer;
  4072.   X, Y: Single;
  4073. begin
  4074.   ACanvas.Pen.Color := FGridColor;
  4075.   ACanvas.Pen.Width := 1;
  4076.   ACanvas.Pen.Style := FGridStyle;
  4077.  
  4078. {do the verticals:}
  4079.   if (FGrid > gtHorizontal) then
  4080.   begin
  4081.     X := FXAxis.StepStart;
  4082.     while (X < FXAxis.Max) do
  4083.     begin
  4084.       iX := FXAxis.FofX(X);
  4085.       if (iX <> FYAxis.MidX) then
  4086.       begin
  4087.         ACanvas.MoveTo(iX, FYAxis.Bottom);
  4088.         ACanvas.LineTo(iX, FYAxis.Top);
  4089.       end;
  4090.       X := FXAxis.GetNextXValue(X);
  4091.     end;
  4092.   end;
  4093.  
  4094. {do the horizontals:}
  4095.   if ((FGrid = gtHorizontal) or (FGrid = gtBoth)) then
  4096.   begin
  4097.     Y := FYAxis.StepStart;
  4098.     while (Y < FYAxis.Max) do
  4099.     begin
  4100.       iY := FYAxis.FofY(Y);
  4101.       if (iY <> FXAxis.MidY) then
  4102.       begin
  4103.         ACanvas.MoveTo(FXAxis.Left, iY);
  4104.         ACanvas.LineTo(FXAxis.Right, iY);
  4105.       end;
  4106.       Y := FYAxis.GetNextXValue(Y);
  4107.     end;
  4108.   end;  
  4109. end;
  4110.  
  4111. {------------------------------------------------------------------------------
  4112.     Procedure: TCustomPlot.DrawWalls
  4113.   Description: painting the graph
  4114.        Author: Mat Ballard
  4115.  Date created: 12/1/1999
  4116. Date modified: 02/25/2000 by Mat Ballard
  4117.       Purpose: draws the grids for 3D plots
  4118.      Comments:
  4119.  Known Issues:
  4120.  ------------------------------------------------------------------------------}
  4121. procedure TCustomPlot.DrawWalls(
  4122.   ACanvas: TCanvas);
  4123. var
  4124.   iX, iY: Integer;
  4125.   X, Y, Z: Single;
  4126.   dZ,
  4127.   TheTickStart: TPoint;
  4128.   TheWall: array[0..3] of TPoint;
  4129. begin
  4130.   ACanvas.Pen.Style := psClear;
  4131.   ACanvas.Brush.Style := bsSolid;
  4132.  
  4133.   dZ.x := FZAxis.EndX - FZAxis.Left;
  4134.   dZ.y := FZAxis.EndY - FZAxis.Top;
  4135.  
  4136. {Calculate the XY wall:}
  4137.   TheWall[0].x := FBorder.Left;
  4138.   TheWall[0].y := FBorder.Top;
  4139.   TheWall[1].x := TheWall[0].x;
  4140.   TheWall[1].y := FBorder.Bottom;
  4141.   TheWall[2].x := FBorder.Right;
  4142.   TheWall[2].y := TheWall[1].y;
  4143.   TheWall[3].x := TheWall[2].x;
  4144.   TheWall[3].y := TheWall[0].y;
  4145. {Draw the XY wall:}
  4146.   ACanvas.Brush.Color := FWallColor;
  4147.   ACanvas.Polygon(TheWall);
  4148.  
  4149. {Calculate the YZ wall:}
  4150.   if (FZAxis.Angle >= 180) then
  4151.   begin
  4152.     TheWall[2].x := TheWall[0].x + dZ.x;
  4153.     TheWall[2].y := TheWall[1].y + dZ.y;
  4154.     TheWall[3].x := TheWall[2].x;
  4155.     TheWall[3].y := TheWall[2].y - FYAxis.Height;
  4156.   end
  4157.   else
  4158.   begin
  4159.     TheWall[0].x := FBorder.Right;
  4160.     TheWall[0].y := FBorder.Top;
  4161.     TheWall[1].x := TheWall[0].x;
  4162.     TheWall[1].y := FBorder.Bottom;
  4163.     TheWall[2].x := TheWall[0].x + dZ.x;
  4164.     TheWall[2].y := TheWall[1].y + dZ.y;
  4165.     TheWall[3].x := TheWall[2].x;
  4166.     TheWall[3].y := TheWall[2].y - FYAxis.Height;
  4167.   end;
  4168.  
  4169. {Draw the YZ left wall:}
  4170.   ACanvas.Brush.Color := Misc.GetDarkerColor(FWallColor, 80);
  4171.   ACanvas.Polygon(TheWall);
  4172.  
  4173. {Calculate the XZ floor:}
  4174.   TheWall[0].x := FBorder.Left;
  4175.   TheWall[0].y := FBorder.Bottom;
  4176. {These four are repeated because if angle < 180 ...}
  4177.   TheWall[1].x := TheWall[0].x + dZ.x;
  4178.   TheWall[1].y := TheWall[0].y + dZ.y;
  4179.   TheWall[2].x := TheWall[1].x + FBorder.Width;
  4180.   TheWall[2].y := TheWall[1].y;
  4181.   TheWall[3].x := FBorder.Right;
  4182.   TheWall[3].y := TheWall[0].y;
  4183.  
  4184. {Draw the XZ left wall:}
  4185.   ACanvas.Brush.Color := GetDarkerColor(FWallColor, 50);
  4186.   ACanvas.Polygon(TheWall);
  4187.  
  4188. {reset pen:}
  4189.   //ACanvas.Pen.Style := psSolid;
  4190.   ACanvas.Brush.Style := bsClear;
  4191.   ACanvas.Pen.Color := FGridColor;
  4192.   ACanvas.Pen.Width := 1;
  4193.   ACanvas.Pen.Style := FGridStyle;
  4194.  
  4195. {do the XY and XZ grids:}
  4196.   if (FGrid > gtHorizontal) then
  4197.   begin
  4198.     X := FXAxis.StepStart;
  4199.     while (X <= FXAxis.Max) do
  4200.     begin
  4201.       iX := FXAxis.FofX(X);
  4202. {XY: vertical |||}
  4203.       ACanvas.MoveTo(iX, FBorder.Top);
  4204.       ACanvas.LineTo(iX, FBorder.Bottom);
  4205. {XZ: vertical ///}
  4206.       //ACanvas.MoveTo(iX, FYAxis.Bottom);
  4207.       ACanvas.LineTo(iX + dZ.x, FBorder.Bottom + dZ.y);
  4208.       X := FXAxis.GetNextXValue(X);
  4209.     end;
  4210.   end;
  4211.  
  4212. {do the XY and YZ grids:}
  4213.   if ((FGrid = gtHorizontal) or (FGrid = gtBoth)) then
  4214.   begin
  4215.     Y := FYAxis.StepStart;
  4216.     while (Y < FYAxis.Max) do
  4217.     begin
  4218.       iY := FYAxis.FofY(Y);
  4219.       if (iY <> FXAxis.MidY) then
  4220.       begin
  4221.         if (FZAxis.Angle >= 180) then
  4222.         begin
  4223. {XY: horizontal ---}
  4224.           ACanvas.MoveTo(FBorder.Right, iY);
  4225.           ACanvas.LineTo(FBorder.Left, iY);
  4226. {YZ: horizontal ///}
  4227.           ACanvas.LineTo(FBorder.Left + dZ.x, iY + dZ.y);
  4228.         end
  4229.         else
  4230.         begin
  4231. {XY: horizontal ---}
  4232.           ACanvas.MoveTo(FBorder.Left, iY);
  4233.           ACanvas.LineTo(FBorder.Right, iY);
  4234. {YZ: horizontal ///}
  4235.           ACanvas.LineTo(FBorder.Right + dZ.x, iY + dZ.y);
  4236.         end;
  4237.  
  4238.       end;
  4239.       Y := FYAxis.GetNextXValue(Y);
  4240.     end;
  4241.   end;
  4242.  
  4243. {do the horizontal Xs and vertical Zs:}
  4244.   Z := FZAxis.StepStart;
  4245.   while (Z < FZAxis.Max) do
  4246.   begin
  4247.     TheTickStart := FZAxis.dFofZ(Z);
  4248.     Inc(TheTickStart.x, FBorder.Left);
  4249.     Inc(TheTickStart.y, FBorder.Bottom);
  4250. {XZ: horizontal: ---}
  4251.     if ((FGrid = gtHorizontal) or (FGrid = gtBoth)) then
  4252.     begin
  4253.       ACanvas.MoveTo(TheTickStart.x + FXAxis.Width, TheTickStart.y);
  4254.       ACanvas.LineTo(TheTickStart.x, TheTickStart.y);
  4255.     end;
  4256. {YZ: vertical}
  4257.     if (FGrid > gtHorizontal) then
  4258.     begin
  4259.       if (FZAxis.Angle >= 180) then
  4260.       begin
  4261.         ACanvas.MoveTo(TheTickStart.x, TheTickStart.y);
  4262.         ACanvas.LineTo(TheTickStart.x, TheTickStart.y - FBorder.Height);
  4263.       end
  4264.       else
  4265.       begin
  4266.         ACanvas.MoveTo(TheTickStart.x + FBorder.Width, TheTickStart.y);
  4267.         ACanvas.LineTo(TheTickStart.x + FBorder.Width, TheTickStart.y - FBorder.Height);
  4268.       end;
  4269.     end;
  4270.     Z := FZAxis.GetNextXValue(Z);
  4271.   end;
  4272. end;
  4273.  
  4274. {------------------------------------------------------------------------------
  4275.     Procedure: TCustomPlot.Trace
  4276.   Description: This traces all series: useful for Oscilloscopes
  4277.        Author: Mat Ballard
  4278.  Date created: 02/25/2000
  4279. Date modified: 02/25/2000 by Mat Ballard
  4280.       Purpose: Draws all Series in erasable mode
  4281.  Known Issues:
  4282.  ------------------------------------------------------------------------------}
  4283. procedure TCustomPlot.Trace;
  4284. var
  4285.   i: Integer;
  4286. begin
  4287. {$IFDEF DELPHI3_UP}
  4288.   Assert(Canvas <> nil, sTraceError);
  4289. {$ENDIF}
  4290.  
  4291.   for i := 0 to FSeriesList.Count-1 do
  4292.   begin
  4293.     TSeries(FSeriesList.Items[i]).Trace(Canvas);
  4294.   end;
  4295. end;
  4296.  
  4297. {------------------------------------------------------------------------------
  4298.     Procedure: TCustomPlot.Resize
  4299.   Description: overrides ancestor's ReSize
  4300.        Author: Mat Ballard
  4301.  Date created: 12/1/1999
  4302. Date modified: 02/25/2000 by Mat Ballard
  4303.       Purpose: responds to a resize of the Plot
  4304.  Known Issues:
  4305.  ------------------------------------------------------------------------------}
  4306.  
  4307. procedure TCustomPlot.Resize;
  4308. var
  4309.   OldIgnoreChanges: Boolean;
  4310. begin
  4311.   OldIgnoreChanges := IgnoreChanges;
  4312.   IgnoreChanges := TRUE;
  4313.   FBorder.RightEx := Width;
  4314.   FBorder.BottomEx := Height;
  4315.   IgnoreChanges := OldIgnoreChanges;
  4316.   SetAxisDimensions;
  4317.   //DoStyleChange(Self);
  4318.   inherited Resize;
  4319. {Required for 3D walls to display properly:}
  4320.   if (FGrid > gtNone) then
  4321.     if (FPlotType >= pt3DContour) then
  4322.     begin
  4323.       Application.ProcessMessages;
  4324.       Refresh;
  4325.     end;
  4326. end;
  4327.  
  4328. {------------------------------------------------------------------------------
  4329.     Procedure: TCustomPlot.StyleChange
  4330.   Description: target of all of the sub-component OnStyleChange events
  4331.        Author: Mat Ballard
  4332.  Date created: 12/1/1999
  4333. Date modified: 02/25/2000 by Mat Ballard
  4334.       Purpose: responds to changes in sub-components
  4335.  Known Issues: get up to 3 screen re-draws
  4336.  ------------------------------------------------------------------------------}
  4337. {procedure TCustomPlot.StyleChange(
  4338.   Sender: TObject);
  4339. begin
  4340.   if (IgnoreChanges) then exit;
  4341.  
  4342.   SetAxisDimensions;
  4343.   DoStyleChange(Self);
  4344. end;}
  4345.  
  4346. {------------------------------------------------------------------------------
  4347.     Procedure: TCustomPlot.DataChange
  4348.   Description: target of TSeriesList (TSeries) OnDataChange event
  4349.        Author: Mat Ballard
  4350.  Date created: 03/07/2001
  4351. Date modified: 03/07/2001 by Mat Ballard
  4352.       Purpose: responds to changes in sub-components
  4353.  Known Issues:
  4354.  ------------------------------------------------------------------------------}
  4355. {procedure TCustomPlot.DataChange(
  4356.   Sender: TObject);
  4357. begin
  4358.   if (IgnoreChanges) then exit;
  4359.  
  4360.   DoDataChange;
  4361. end;}
  4362.  
  4363. {Mousey stuff -----------------------------------------------------------------}
  4364.  
  4365. {------------------------------------------------------------------------------
  4366.     Procedure: TCustomPlot.DblClick
  4367.   Description: overrides ancestor's DblClick
  4368.        Author: Mat Ballard
  4369.  Date created: 12/1/1999
  4370. Date modified: 02/25/2000 by Mat Ballard
  4371.       Purpose: activates in-place editing of titles
  4372.  Known Issues:
  4373.  ------------------------------------------------------------------------------}
  4374. procedure TCustomPlot.DblClick;
  4375. var
  4376.   i: Integer;
  4377.   TheRect: TRect;
  4378.   TheCaption: TCaption;
  4379.   TheRight: Integer;
  4380. begin
  4381. {get rid of the mouse moving timer:}
  4382.   MouseTimer.Enabled := FALSE;
  4383.  
  4384.   if (FEditable) then
  4385.   begin
  4386.     if ((ClickedObjectType = soTitle) or
  4387.         (ClickedObjectType = soXAxisTitle) or
  4388.         (ClickedObjectType = soYAxisTitle) or
  4389.         (ClickedObjectType = soNote)) then
  4390.     begin
  4391.       FScreenJob := sjFlashEdit;
  4392.       TheCaption := TCaption(pClickedObject);
  4393. {create the in-place editor:}
  4394.       CreateFlashEditor;
  4395. {... and initialize it:}
  4396.       if (ClickedObjectType = soNote) then
  4397.         FFlashEdit.Text := TheCaption.Caption
  4398.        else
  4399.         FFlashEdit.Text := TTitle(pClickedObject).FullCaption;
  4400.       FFlashEdit.Height := TheCaption.Height + 10;
  4401.       FFlashEdit.Width  := 2 * TheCaption.Width;
  4402.       if (FFlashEdit.Height > FFlashEdit.Width) then
  4403.       begin
  4404. {height > width, so it is a vertical caption:}
  4405.         i := FFlashEdit.Height;
  4406.         FFlashEdit.Height := FFlashEdit.Width;
  4407.         FFlashEdit.Width := i;
  4408.       end;
  4409.       FFlashEdit.Top := TheCaption.Top;
  4410. {Have to check that the edit box is on-screen:}
  4411.       TheRight := TheCaption.Left + FFlashEdit.Width;
  4412.       if (TheRight > Width) then
  4413.         FFlashEdit.Left := TheCaption.Right - FFlashEdit.Width
  4414.       else
  4415.         FFlashEdit.Left := TheCaption.Left;
  4416.  
  4417.       FFlashEdit.Tag := Ord(ClickedObjectType);
  4418.       FFlashEdit.Font.Assign(TheCaption.Font);
  4419.  
  4420.       FFlashEdit.Visible := TRUE;
  4421.       FFlashEdit.SetFocus;
  4422.     end {Title or axis caption}
  4423.     else if (ClickedObjectType = soLegend) then
  4424.     begin
  4425.       FScreenJob := sjFlashEdit;
  4426. {create the in-place editor:}
  4427.       CreateFlashEditor;
  4428.       TheSeries := FLegend.GetHit(Selection.Left, Selection.Top, TheRect);
  4429.       FFlashEdit.Height := FLegend.FontHeight + 2;
  4430.       FFlashEdit.Width  := FLegend.ItemWidth;
  4431.       FFlashEdit.Left := TheRect.Left;
  4432.       FFlashEdit.Top := TheRect.Top - 1;
  4433.       FFlashEdit.Tag := Ord(soLegend);
  4434. {we use HelpContext because MouseDown is called after DblClick, which nukes TheSeries:}
  4435.       FFlashEdit.HelpContext := TheSeries;
  4436.       FFlashEdit.Font.Assign(FLegend.Font);
  4437.       FFlashEdit.Text := TSeries(FSeriesList[TheSeries]).Name;
  4438.       FFlashEdit.Visible := TRUE;
  4439.       FFlashEdit.SetFocus;
  4440.     end; {Legend}
  4441.   end; {editable}
  4442.  
  4443.   inherited DblClick;
  4444. end;
  4445.  
  4446. {------------------------------------------------------------------------------
  4447.     Procedure: TCustomPlot.CreateFlashEditor
  4448.   Description: Creates the FlashEdit in-place editor
  4449.        Author: Mat Ballard
  4450.  Date created: 12/1/1999
  4451. Date modified: 02/25/2000 by Mat Ballard
  4452.       Purpose: caption management
  4453.  Known Issues:
  4454.  ------------------------------------------------------------------------------}
  4455. procedure TCustomPlot.CreateFlashEditor;
  4456. {create the in-place editor:}
  4457. begin
  4458.   if (FFlashEdit = nil) then
  4459.   begin
  4460.     FFlashEdit := TEdit.Create(nil);
  4461.     FFlashEdit.Parent := Self;
  4462.     FFlashEdit.OnKeyDown := FlashEditKeyDown;
  4463.     FFlashEdit.OnExit := FlashEditExit;
  4464.     FFlashEdit.Hint := sFlashEditHint;
  4465.     FFlashEdit.ShowHint := TRUE;
  4466.   end;
  4467. end;
  4468.  
  4469. {------------------------------------------------------------------------------
  4470.     Procedure: TCustomPlot.FlashEditKeyDown
  4471.   Description: KeyDown event handler of FFlashEdit in-place editor
  4472.        Author: Mat Ballard
  4473.  Date created: 12/1/1999
  4474. Date modified: 02/25/2000 by Mat Ballard
  4475.       Purpose: Cancel the FFlashEditor if Esc pressed, or save the changed Title.
  4476.  Known Issues:
  4477.  ------------------------------------------------------------------------------}
  4478. procedure TCustomPlot.FlashEditKeyDown(
  4479.   Sender: TObject;
  4480.   var Key: Word;
  4481.   Shift: TShiftState);
  4482. begin
  4483.   if (Key = VK_ESCAPE) then  //4096
  4484.   begin
  4485.     FFlashEdit.Visible := FALSE;
  4486.     Key := 0;
  4487.   end;
  4488.  
  4489.   if (Key = VK_RETURN) then //4100
  4490.   begin
  4491. {this will throw an exception if Tag is not a valid TObjectType:}
  4492.     case TObjectType(FFlashEdit.Tag) of
  4493.       soTitle: FTitle.Caption := FFlashEdit.Text;
  4494.       {soXAxis, soYAxis}
  4495.       soXAxisTitle: FXAxis.Title.Caption := FFlashEdit.Text;
  4496.       soYAxisTitle: TTitle(pClickedObject).Caption := FFlashEdit.Text;
  4497.       {soXAxisLabel, soYAxisLabel, soYAxis2Label,
  4498.       soLeftBorder, soTopBorder, soRightBorder, soBottomBorder}
  4499. {we use HelpContext because MouseDown is called after DblClick, which nukes TheSeries:}
  4500.       soLegend: TSeries(FSeriesList[FFlashEdit.HelpContext]).Name := FFlashEdit.Text;
  4501.       soNote: TNote(pClickedObject).Caption := FFlashEdit.Text;
  4502.     end;
  4503.     FFlashEdit.Visible := FALSE;
  4504.     Key := 0;
  4505.     DoStyleChange(Self);
  4506.   end;
  4507. end;
  4508.  
  4509. {------------------------------------------------------------------------------
  4510.     Procedure: TCustomPlot.FlashEditExit
  4511.   Description: Exit event handler of FFlashEdit in-place editor
  4512.        Author: Mat Ballard
  4513.  Date created: 12/1/1999
  4514. Date modified: 02/25/2000 by Mat Ballard
  4515.       Purpose: hide the FFlashEditor
  4516.  Known Issues:
  4517.  ------------------------------------------------------------------------------}
  4518. procedure TCustomPlot.FlashEditExit(
  4519.   Sender: TObject);
  4520. begin
  4521.   FFlashEdit.Visible := FALSE;
  4522.   FFlashEdit.Text := '';
  4523.   ZeroScreenStuff;
  4524. end;
  4525.  
  4526. {------------------------------------------------------------------------------
  4527.     Procedure: TCustomPlot.KeyDown
  4528.   Description: KeyDown event handler
  4529.        Author: Mat Ballard
  4530.  Date created: 04/22/2001
  4531. Date modified: 04/22/2001 by Mat Ballard
  4532.       Purpose: This processes certain key strokes.
  4533.  Known Issues: Does not work: a CustomPanel does not seem to be able to gain focus.
  4534.  ------------------------------------------------------------------------------}
  4535. {procedure TCustomPlot.KeyDown(var Key: Word; Shift: TShiftState);
  4536. var
  4537.   OldVar, Gap: Single;
  4538. begin
  4539.   case Key of
  4540.     VK_LEFT:
  4541.       begin
  4542.         if (ssCtrl in Shift) then
  4543.         begin
  4544.           if (FXAxis.Min > FSeriesList.Xmin) then
  4545.           begin
  4546.             OldVar := FXAxis.Min;
  4547.             Gap := FXAxis.Max - FXAxis.Min;
  4548.             FXAxis.Min := FXAxis.Min - Gap;
  4549.             FXAxis.Max := FXAxis.Max - Gap;
  4550.           end;
  4551.         end;
  4552.       end;
  4553.     VK_RIGHT:
  4554.       begin
  4555.         if (ssCtrl in Shift) then
  4556.         begin
  4557.           if (FXAxis.Max < FSeriesList.Xmax) then
  4558.           begin
  4559.             OldVar := FXAxis.Max;
  4560.             Gap := FXAxis.Max - FXAxis.Min;
  4561.             FXAxis.Max := FXAxis.Max + Gap;
  4562.             FXAxis.Min := FXAxis.Min + Gap;
  4563.           end;
  4564.         end;
  4565.       end;
  4566.   end;
  4567.  
  4568.   inherited KeyDown(Key, Shift);
  4569. end;}
  4570.  
  4571. {------------------------------------------------------------------------------
  4572.     Procedure: TCustomPlot.MouseDown
  4573.   Description: MouseDown event handler
  4574.        Author: Mat Ballard
  4575.  Date created: 12/1/1999
  4576. Date modified: 08/31/2000 by Mat Ballard
  4577.       Purpose: The start of all mouse routines
  4578.  Known Issues: MouseDown gets called AFTER DblClick !
  4579.       Changes: GetTheClickedObject now moved to within the 'if (FScreenJob = sjNone) then'
  4580.  ------------------------------------------------------------------------------}
  4581. procedure TCustomPlot.MouseDown(
  4582.   Button: TMouseButton;
  4583.   Shift: TShiftState;
  4584.   X,
  4585.   Y: Integer);
  4586. begin
  4587. {Nuke any Caption:}
  4588.   FInstructions.Clear;
  4589.  
  4590. {record the beginning:}
  4591.   MouseStart.x := X;
  4592.   MouseStart.y := Y;
  4593. {set the moving object co-ordinates:}
  4594.   Selection.MoveTo(X, Y);
  4595.   Selection.Height := 1;
  4596.   Selection.Width := 1;
  4597.  
  4598. {  if (FScreenJob <> sjFlashEdit) then
  4599.     FFlashEdit.Visible := FALSE;}
  4600.  
  4601. {if no ScreenJob has been set yet, it could be several things:}
  4602.   if (FScreenJob = sjNone) then
  4603.   begin
  4604. {no job yet}
  4605. {what got clicked ?}
  4606.     GetTheClickedObject(X, Y);
  4607.     if (Button = mbLeft) then
  4608.     begin
  4609. {left click:}
  4610.       if (ssShift in Shift) then
  4611.       begin
  4612. {We want to zoom in:}
  4613.         FScreenJob := sjZoomIn;
  4614.       end
  4615.       else if ((ClickedObjectType <> soNone) and
  4616.                (FMovable)) then
  4617.       begin
  4618. {left clicks can lead to click and drag:}
  4619.         MouseTimer.Enabled := TRUE;
  4620.       end;
  4621.     end; {left button}
  4622.     {NOTE: if it is the right button, then the popup menu will be displayed
  4623.      at the end of the MouseUp}
  4624.   end; {if sjNone}
  4625.  
  4626.   case FScreenJob of
  4627.     {sjNone: already done}
  4628.     {sjDrag: set by MouseTimeOut
  4629.     sjRightDrag: set in MouseMove}
  4630.     sjHide: HideClick(Self);
  4631.     sjZoomIn:
  4632.       begin
  4633.         Screen.Cursor := crSize;
  4634.         OutlineTheClickedObject;
  4635.       end;
  4636.     {sjEditAxis:}
  4637.     {sjTouchNote:}
  4638.     sjMoveNotePointer: ZeroScreenStuff;
  4639.     {sjEditFont:
  4640.     sjEditPoint:
  4641.     sjEditSeries:
  4642.     sjCopySeries: ;
  4643.     sjDisplace:   ;
  4644.     sjCloneSeries: ;
  4645.     sjDeleteSeries: all done by popupmenu or option}
  4646.     sjPosition: PositionClick(Self);
  4647.     sjNearestPoint: NearestPointClick(Self);
  4648.     sjLinearize,
  4649.     sjZero,
  4650.     sjAverage,
  4651.     sjContractSeries,
  4652.     sjContractAllSeries,
  4653.     {sjSplineSeries: ;
  4654.     sjHighs,
  4655.     sjLows,
  4656.     sjMovingAverage,
  4657.     sjSmoothSeries:   ;
  4658.     sjSortSeries: ;
  4659.     sjDifferentiate:   ;
  4660.     sjIntegrate: all done by popupmenu or option}
  4661.     sjIntegral,
  4662.     sjLineOfBestFit,
  4663.     sjDualLineBestFit1,
  4664.     sjDualLineBestFit2,
  4665.     sjSelection,
  4666.     sjDualSelection1,
  4667.     sjDualSelection2:
  4668.       begin
  4669.         Screen.Cursor := crSize;
  4670.         Selection.Outline(Canvas);
  4671.       end;
  4672.   end;
  4673.  
  4674.   inherited MouseDown(Button, Shift, X, Y);
  4675. end;
  4676.  
  4677. {------------------------------------------------------------------------------
  4678.     Procedure: TCustomPlot.MouseMove
  4679.   Description: MouseMove event handler
  4680.        Author: Mat Ballard
  4681.  Date created: 12/1/1999
  4682. Date modified: 02/25/2000 by Mat Ballard
  4683.       Purpose: Moves the dashed outline around the screen; how it moves depends on the object
  4684.  Known Issues:
  4685.  ------------------------------------------------------------------------------}
  4686. procedure TCustomPlot.MouseMove(
  4687.   Shift: TShiftState;
  4688.   X,
  4689.   Y: Integer);
  4690. var
  4691.   Gap,
  4692.   NewLeft,
  4693.   NewTop,
  4694.   dx, dy: Integer;
  4695.   Ptr: Pointer;
  4696. begin
  4697.   MouseTimer.Enabled := FALSE;
  4698.  
  4699.   if (FScreenJob = sjMoveNotePointer) then
  4700.     TNote(pClickedObject).TracePointerTo(Canvas, X, Y);
  4701.  
  4702.   if (ssLeft in Shift) then
  4703.   begin
  4704.     case FScreenJob of
  4705.       {sjNone:}
  4706.       sjDrag:
  4707.         case ClickedObjectType of
  4708.           soTitle:
  4709.             begin
  4710.               if (X < (FBorder.Left + FBorder.MidX) div 2) then
  4711.                 NewLeft := FBorder.Left
  4712.               else if (X > (FBorder.Right + FBorder.MidX) div 2) then
  4713.                 NewLeft := FBorder.Right - Selection.Width
  4714.               else
  4715.                 NewLeft := FBorder.MidX - Selection.Width div 2;
  4716.               if (Y > FXAxis.MidY) then
  4717.                 NewTop := Height - BevelGap - FTitle.Height
  4718.               else
  4719.                 NewTop := BevelGap;
  4720.               MoveTheClickedObjectTo(NewLeft, NewTop);
  4721.             end;
  4722.           soXAxis, soTopBorder, soBottomBorder:
  4723.             begin
  4724.               MoveTheClickedObjectTo(
  4725.                 TRectangle(pClickedObject).Left,
  4726.                 Y - ClickedObjectOffset.y);
  4727.             end;
  4728.           soYAxis, soLeftBorder, soRightBorder:
  4729.             begin
  4730.               MoveTheClickedObjectTo(
  4731.                 X - ClickedObjectOffset.x,
  4732.                 TRectangle(pClickedObject).Top);
  4733.             end;
  4734.           soZAxis:
  4735.             begin
  4736.               dx := X - MouseStart.x;
  4737.               dy := Y - MouseStart.y;
  4738.               if (Abs(dx) >= Abs(dy)) then
  4739.                 MoveTheClickedObjectTo(
  4740.                   X - ClickedObjectOffset.x,
  4741.                   TRectangle(pClickedObject).Top)
  4742.                else
  4743.                 MoveTheClickedObjectTo(
  4744.                   TRectangle(pClickedObject).Left,
  4745.                   Y - ClickedObjectOffset.y);
  4746.             end;
  4747.           soXAxisTitle:
  4748.             begin
  4749.               if (X < (FBorder.Left + FBorder.MidX) div 2) then
  4750.                 NewLeft := FBorder.Left
  4751.               else if (X > (FBorder.Right + FBorder.MidX) div 2) then
  4752.                 NewLeft := FBorder.Right - Selection.Width
  4753.               else
  4754.                 NewLeft := FBorder.MidX - Selection.Width div 2;
  4755.               Gap := Abs(FXAxis.Title.MidY - FXAxis.MidY);
  4756.               if (Y > FXAxis.MidY) then
  4757.                 NewTop := FXAxis.MidY + Gap - FXAxis.Title.Height div 2
  4758.               else
  4759.                 NewTop := FXAxis.MidY - Gap - FXAxis.Title.Height div 2;
  4760.               MoveTheClickedObjectTo(NewLeft, NewTop);
  4761.             end;
  4762.           soYAxisTitle:
  4763.             begin
  4764. {Which Y Axis owns this Title ?}
  4765.               Ptr := TRectangle(pClickedObject).Owner;
  4766.               Gap := Abs(TRectangle(pClickedObject).MidX - TAxis(Ptr).MidX);
  4767.               if (X < TAxis(Ptr).MidX) then
  4768.                 NewLeft := TAxis(Ptr).MidX - Gap - TRectangle(pClickedObject).Width div 2
  4769.               else
  4770.                 NewLeft := TAxis(Ptr).MidX + Gap - TRectangle(pClickedObject).Width div 2;
  4771.               if (Y < (FBorder.Top + FBorder.MidY) div 2) then
  4772.                 NewTop := FBorder.Top
  4773.               else if (Y > (FBorder.Bottom + FBorder.MidY) div 2) then
  4774.                 NewTop := FBorder.Bottom - Selection.Height
  4775.               else
  4776.                 NewTop := FBorder.MidY - Selection.Height div 2;
  4777.               MoveTheClickedObjectTo(NewLeft, NewTop);
  4778.             end;
  4779.           soXAxisLabel:
  4780.             begin
  4781.               Gap := Abs(FXAxis.Labels.MidY - FXAxis.MidY);
  4782.               if (Y < FXAxis.MidY) then
  4783.                 MoveTheClickedObjectTo(Selection.Left,
  4784.                   FXAxis.MidY - Gap - FXAxis.Labels.Height div 2)
  4785.               else
  4786.                 MoveTheClickedObjectTo(Selection.Left,
  4787.                   FXAxis.MidY + Gap - FXAxis.Labels.Height div 2);
  4788.             end;
  4789.           soYAxisLabel:
  4790.             begin
  4791. {Which Y Axis owns this Title ?}
  4792.               Ptr := TRectangle(pClickedObject).Owner;
  4793.               Gap := Abs(TRectangle(pClickedObject).MidX - TAxis(Ptr).MidX);
  4794.               if (X < TAxis(Ptr).MidX) then
  4795.                 MoveTheClickedObjectTo(
  4796.                   TAxis(Ptr).MidX - Gap - TRectangle(pClickedObject).Width div 2,
  4797.                   Selection.Top)
  4798.               else
  4799.                 MoveTheClickedObjectTo(
  4800.                   TAxis(Ptr).MidX + Gap - TRectangle(pClickedObject).Width div 2,
  4801.                   Selection.Top);
  4802.             end;
  4803.           soLegend, soResult, soNote:
  4804.             begin {both of these can move freely:}
  4805.               MoveTheClickedObjectTo(
  4806.                 X - ClickedObjectOffset.x,
  4807.                 Y - ClickedObjectOffset.y);
  4808.             end;
  4809.           soSeries:
  4810.             begin
  4811.               pSeries.MoveBy(Canvas, FPlotType, X-Selection.Left, Y-Selection.Top, FOutlineWidth);
  4812.               Selection.MoveTo(X, Y);
  4813.             end;
  4814.         end; {end case sjDrag}
  4815.       {sjHide:}
  4816.       sjZoomIn:
  4817.         StretchTheClickedObjectTo(X, Y);
  4818.       {sjEditAxis: ;}
  4819.       {sjEditFont: ;
  4820.       sjEditPoint: ;
  4821.       sjEditSeries: ;
  4822.       sjCopySeries: ;
  4823.       sjDisplace:   ;
  4824.       sjCloneSeries: ;
  4825.       sjDeleteSeries: all done by popupmenu or option}
  4826.       {sjPosition: already done, or by popupmenu}
  4827.       {sjNearestPoint: already done, or by popupmenu}
  4828.       sjLinearize,
  4829.       sjZero,
  4830.       sjAverage,
  4831.       sjContractSeries,
  4832.       sjContractAllSeries,
  4833.       {sjSplineAxis: ;
  4834.       sjHighs,
  4835.       sjLows,
  4836.       sjMovingAverage,
  4837.       sjSmoothSeries:   ;
  4838.       sjSortSeries: ;
  4839.       sjDifferentiate:   ;
  4840.       sjIntegrate: all done by popupmenu or option}
  4841.       sjIntegral,
  4842.       sjLineOfBestFit,
  4843.       sjDualLineBestFit1,
  4844.       sjDualLineBestFit2,
  4845.       sjSelection,
  4846.       sjDualSelection1,
  4847.       sjDualSelection2:
  4848.         StretchTheClickedObjectTo(X, Y);
  4849.     end;
  4850.   end {if (ssLeft in Shift)}
  4851.   else if (ssRight in Shift) then
  4852.   begin {aha ! a right click and drag operation !}
  4853.     FScreenJob := sjRightDrag;
  4854.     StretchTheClickedObjectTo(X, Y);
  4855.   end;
  4856.  
  4857.   inherited MouseMove(Shift, X, Y);
  4858. end;
  4859.  
  4860. {------------------------------------------------------------------------------
  4861.     Procedure: TCustomPlot.MouseUp
  4862.   Description: MouseUp event handler
  4863.        Author: Mat Ballard
  4864.  Date created: 12/1/1999
  4865. Date modified: 05/30/2001 by Mat Ballard
  4866.       Purpose: Reacts to the user finishing an action with the mouse
  4867.  Known Issues:
  4868.  ------------------------------------------------------------------------------}
  4869. procedure TCustomPlot.MouseUp(
  4870.   Button: TMouseButton;
  4871.   Shift: TShiftState;
  4872.   X,
  4873.   Y: Integer);
  4874. var
  4875.   Point: TPoint;
  4876. begin
  4877.   MouseTimer.Enabled := FALSE;
  4878.  
  4879.   if (Button = mbLeft) then
  4880.   begin
  4881.     case FScreenJob of
  4882.       {sjNone:}
  4883.       sjDrag:
  4884.         begin
  4885.           OutlineTheClickedObject;
  4886.           if (SecondClickedObjectType = soNone) then
  4887.           begin
  4888.             MoveTheClickedObjectClick(Self);
  4889.           end
  4890.           else
  4891.           begin
  4892.             Point.x := X;
  4893.             Point.y := Y;
  4894.             Point := ClientToScreen(Point);
  4895.             if (pClickedObject <> nil) then
  4896.               WhichPopUpItems[0].Caption := sMoveThe +
  4897.                 TRectangle(pClickedObject).Name;
  4898.             if (pSecondClickedObject <> nil) then
  4899.               WhichPopUpItems[1].Caption := sMoveThe +
  4900.                 TRectangle(pSecondClickedObject).Name;
  4901.             WhichPopUpMenu.Popup(Point.x, Point.y);
  4902.           end;
  4903.         end;
  4904.       {sjHide:}
  4905.       sjZoomIn:
  4906.         begin
  4907.           OutlineTheClickedObject;
  4908.           SwapEnds;
  4909.           ZoomInClick(Self);
  4910.         end;
  4911.       {sjEditAxis: ;}
  4912.       sjMoveNotePointer: ZeroScreenStuff;
  4913.       {sjEditFont: ;
  4914.       sjEditPoint: ;
  4915.       sjEditSeries: ;
  4916.       sjCopySeries: ;
  4917.       sjDisplace:   ;
  4918.       sjCloneSeries: ;
  4919.       sjDeleteSeries: ;}
  4920.       {sjPosition: already done, or by popupmenu}
  4921.       {sjNearestPoint: already done, or by popupmenu}
  4922.       sjAverage:
  4923.         begin
  4924.           Selection.Outline(Canvas);
  4925.           SwapEnds;
  4926.           AverageClick(Self);
  4927.         end;
  4928.       sjLinearize:
  4929.         begin
  4930.           Selection.Outline(Canvas);
  4931.           SwapEnds;
  4932.           LinearizeClick(Self);
  4933.         end;
  4934.       sjZero:
  4935.         begin
  4936.           Selection.Outline(Canvas);
  4937.           SwapEnds;
  4938.           ZeroClick(Self);
  4939.         end;
  4940.       sjContractSeries:
  4941.         begin
  4942.           Selection.Outline(Canvas);
  4943.           SwapEnds;
  4944.           ContractSeriesClick(Self);
  4945.         end;
  4946.       sjContractAllSeries:
  4947.         begin
  4948.           Selection.Outline(Canvas);
  4949.           SwapEnds;
  4950.           ContractAllSeriesClick(Self);
  4951.         end;
  4952.       {sjSplineSeries: ;
  4953.       sjHighs,
  4954.       sjLows,
  4955.       sjMovingAverage,
  4956.       sjSmoothSeries:   ;
  4957.       sjSortSeries: ;
  4958.       sjDifferentiate:   ;
  4959.       sjIntegrate:        ;}
  4960.       sjIntegral:
  4961.         begin
  4962.           Selection.Outline(Canvas);
  4963.           SwapEnds;
  4964.           IntegralClick(Self);
  4965.         end;
  4966.       sjLineOfBestFit:
  4967.         begin
  4968.           Selection.Outline(Canvas);
  4969.           SwapEnds;
  4970.           LineBestFitClick(Self);
  4971.         end;
  4972.       sjDualLineBestFit1:
  4973.         begin
  4974.           Selection.Outline(Canvas);
  4975.           SwapEnds;
  4976.           TwoRegionLineBestFitClick(Self);
  4977.         end;
  4978.       sjDualLineBestFit2:
  4979.         begin
  4980.           Selection.Outline(Canvas);
  4981.           SwapEnds;
  4982.           LineBestFitClick(Self);
  4983.         end;
  4984.       sjSelection:
  4985.         begin
  4986.           Selection.Outline(Canvas);
  4987.           SwapEnds;
  4988.           Selection.AssignToRect(Sel1);
  4989.           DoSelection(Sel1);
  4990.         end;
  4991.       sjDualSelection1:
  4992.         begin
  4993.           Selection.Outline(Canvas);
  4994.           SwapEnds;
  4995.           Selection.AssignToRect(Sel1);
  4996.           ScreenJob := sjDualLineBestFit2;
  4997.           FInstructions.Clear;
  4998.           FInstructions.Add(sDualInstruction);
  4999.           DoStyleChange(Self);
  5000.         end;
  5001.       sjDualSelection2:
  5002.         begin
  5003.           Selection.Outline(Canvas);
  5004.           SwapEnds;
  5005.           Selection.AssignToRect(Sel2);
  5006.           DoDualSelection(Sel1, Sel2);
  5007.         end;
  5008.     end; {end case}
  5009.     DoStyleChange(Self);
  5010.   end {end Left Button}
  5011.   else
  5012.   begin {Right Button}
  5013.     OutlineTheClickedObject;
  5014. {$IFNDEF DELPHI1}
  5015. {what does that do to menu visibility ?}
  5016.     DetermineMenuVisibility;
  5017. {$ENDIF}
  5018. {we no longer let the ancestor run the popup:
  5019.  see note above on 'property PopupMenu':}
  5020.     Point.x := X;
  5021.     Point.y := Y;
  5022.     Point := ClientToScreen(Point);
  5023.     if (FScreenJob = sjRightDrag) then
  5024.       FDragPopUpMenu.Popup(Point.x, Point.y)
  5025.      else
  5026.       FPlotPopUpMenu.Popup(Point.x, Point.y);
  5027.   end; {end Right Button}
  5028.  
  5029. {inherited runs the popup if neccessary:}
  5030.   inherited MouseUp(Button, Shift, X, Y);
  5031. end;
  5032.  
  5033. {------------------------------------------------------------------------------
  5034.     Procedure: TCustomPlot.DoSelection
  5035.   Description: Fires the Selection event
  5036.        Author: Mat Ballard
  5037.  Date created: 09/07/2000
  5038. Date modified: 09/07/2000 by Mat Ballard
  5039.       Purpose:
  5040.  Known Issues:
  5041.  ------------------------------------------------------------------------------}
  5042. procedure TCustomPlot.DoSelection(Sel1: TRect);
  5043. begin
  5044.   if Assigned(FOnSelection) then
  5045.     OnSelection(Self, Sel1);
  5046. end;
  5047.  
  5048. {------------------------------------------------------------------------------
  5049.     Procedure: TCustomPlot.DoDualSelection
  5050.   Description: Fires the DualSelection event
  5051.        Author: Mat Ballard
  5052.  Date created: 09/07/2000
  5053. Date modified: 09/07/2000 by Mat Ballard
  5054.       Purpose:
  5055.  Known Issues:
  5056.  ------------------------------------------------------------------------------}
  5057. procedure TCustomPlot.DoDualSelection(Sel1, Sel2: TRect);
  5058. begin
  5059.   if Assigned(FOnDualSelection) then
  5060.     OnDualSelection(Self, Sel1, Sel2);
  5061. end;
  5062.  
  5063. {$IFNDEF DELPHI1}
  5064. {------------------------------------------------------------------------------
  5065.     Procedure: TCustomPlot.DetermineMenuVisibility
  5066.   Description: Sets the visibility of Axis-related menus
  5067.        Author: Mat Ballard
  5068.  Date created: 04/17/2000
  5069. Date modified: 04/17/2000 by Mat Ballard
  5070.       Purpose: menu management
  5071.  Known Issues:
  5072.  ------------------------------------------------------------------------------}
  5073. procedure TCustomPlot.DetermineMenuVisibility;
  5074. var
  5075.   i: Integer;
  5076.   SeriesVisibility: Boolean;
  5077. begin
  5078. {$IFDEF SHOWALLMENUS}
  5079.   exit;
  5080. {$ENDIF}
  5081.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].Enabled := CanPaste;
  5082.  
  5083.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  5084.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].Visible := FALSE;
  5085.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := FALSE;
  5086.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Visible := FALSE;
  5087.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Visible := FALSE;
  5088.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Visible := FALSE;
  5089.   SeriesVisibility := FALSE;
  5090.  
  5091.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuClearOverlays)].Visible :=
  5092.     (FirstOverlay >= 0);
  5093.  
  5094.   case ClickedObjectType of
  5095.     soTitle,
  5096.     soXAxisTitle, soYAxisTitle,
  5097.     soXAxisLabel, soYAxisLabel,
  5098.     soResult:
  5099.       begin
  5100.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  5101.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := TRUE;
  5102.       end;
  5103.     soNote:
  5104.       begin
  5105.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  5106.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := TRUE;
  5107.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Visible :=
  5108.           (NoteCount > 0);
  5109.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Visible :=
  5110.           (NoteCount > 0);
  5111.       end;
  5112.     soLegend:
  5113.       begin
  5114.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  5115.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Visible := TRUE;
  5116.         if (FSeriesList.Count > 1) then
  5117.         begin
  5118.           FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Visible := TRUE;
  5119.         end;
  5120.       end;
  5121.     soXAxis, soYAxis, soZAxis:
  5122.       begin
  5123.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  5124.         FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditAxis)].Visible := TRUE;
  5125.       end;
  5126.     soSeries:
  5127.       begin
  5128.         //pSeries.OutlineSeries(FOutlineWidth, Canvas);
  5129.         FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := TRUE;
  5130.         SeriesVisibility := TRUE;
  5131.       end;
  5132.   else
  5133.     {soLeftBorder, soTopBorder, soRightBorder, soBottomBorder:}
  5134.     begin
  5135.       FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Visible := FALSE;
  5136.     end;
  5137.   end;
  5138.   SetSeriesVisibility(SeriesVisibility);
  5139.  
  5140.   for i := 0 to Ord(High(TMainMenus)) do
  5141.     FPlotPopUpMenu.Items[i].Visible :=
  5142.       FPlotPopUpMenu.Items[i].Visible and
  5143.         (TMainMenus(i) in FPopupOptions.Menu);
  5144.   for i := 0 to Ord(High(TFileMenus)) do
  5145.     FPlotPopUpMenu.Items[Ord(mnuFile)].Items[i].Visible :=
  5146.       FPlotPopUpMenu.Items[Ord(mnuFile)].Items[i].Visible and
  5147.         (TFileMenus(i) in FPopupOptions.File_);
  5148.   for i := 0 to Ord(High(TEditMenus)) do
  5149.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[i].Visible :=
  5150.       FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[i].Visible and
  5151.         (TEditMenus(i) in FPopupOptions.Edit);
  5152.   for i := 0 to Ord(High(TViewMenus)) do
  5153.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[i].Visible :=
  5154.       FPlotPopUpMenu.Items[Ord(mnuView)].Items[i].Visible and
  5155.         (TViewMenus(i) in FPopupOptions.View);
  5156.   for i := 0 to Ord(High(TCalcMenus)) do
  5157.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[i].Visible :=
  5158.       FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[i].Visible and
  5159.         (TCalcMenus(i) in FPopupOptions.Calc);
  5160.  
  5161.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].Visible :=
  5162.       FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Visible;
  5163. {NewSeries means that this divider is now always visible:
  5164.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].Visible :=
  5165.     FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Visible;}
  5166.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].Visible :=
  5167.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Visible;
  5168.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].Visible :=
  5169.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Visible;
  5170. end;
  5171.  
  5172. {------------------------------------------------------------------------------
  5173.     Procedure: TCustomPlot.SetSeriesVisibility
  5174.   Description: Sets the visibility of Axis-related menus
  5175.        Author: Mat Ballard
  5176.  Date created: 04/17/2000
  5177. Date modified: 04/17/2000 by Mat Ballard
  5178.       Purpose: menu management
  5179.  Known Issues:
  5180.  ------------------------------------------------------------------------------}
  5181. procedure TCustomPlot.SetSeriesVisibility(Value: Boolean);
  5182. begin
  5183. {Can't do anything to Series if there is no data:}
  5184.   Value := Value and (FSeriesList.TotalNoPts > 0);
  5185.  
  5186. {The following are independent of whether or not a Series has been selected:}
  5187.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSave)].Visible :=
  5188.     (FSeriesList.TotalNoPts > 0) and FSeriesList.DataChanged;
  5189.   FPlotPopUpMenu.Items[Ord(mnuFile)].Items[Ord(mnuSaveAs)].Visible :=
  5190.     (FSeriesList.TotalNoPts > 0);
  5191.  
  5192.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].Visible :=
  5193.     (FAxisList.Count > 2);
  5194.  
  5195.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].Visible :=
  5196.  
  5197.     (FSeriesList.TotalNoPts > 0);
  5198.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].Visible :=
  5199.     (FSeriesList.TotalNoPts > 20);
  5200.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].Visible :=
  5201.     (FSeriesList.TotalNoPts > 20);
  5202. {$IFDEF FUNCTIONS}
  5203.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].Visible := (FSeriesList.Count > 0);
  5204.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].Visible := (FSeriesList.Count > 0);
  5205. {$ENDIF}
  5206.  
  5207. {The following DO DEPEND on whether or not a Series has been selected:}
  5208.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].Visible := Value;
  5209.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].Visible := Value;
  5210.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Visible := Value;
  5211.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].Visible := Value;
  5212.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].Visible := Value;
  5213.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].Visible := Value;
  5214.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].Visible := Value;
  5215.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Visible := Value;
  5216.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].Visible := Value;
  5217.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].Visible := Value;
  5218.   FPlotPopUpMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].Visible := Value;
  5219.  
  5220.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Visible := Value;
  5221.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Visible :=
  5222.     Value and
  5223.     (FSeriesList.TotalNoPts > 20) and
  5224.     (pSeries <> nil) and
  5225.     (not ((pSeries.ExternalXSeries) or (pSeries.XDataRefCount > 0)));
  5226.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].Visible :=
  5227.     FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Visible;
  5228.  
  5229.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSpline)].Visible := Value;
  5230.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].Visible := Value;
  5231.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].Visible := Value;
  5232.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].Visible := Value;
  5233.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].Visible := Value;
  5234.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].Visible := Value;
  5235.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].Visible := Value;
  5236.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].Visible := Value;
  5237.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].Visible := Value;
  5238.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Visible := Value;
  5239.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].Visible := Value;
  5240. end;
  5241.  
  5242. {------------------------------------------------------------------------------
  5243.     Procedure: TCustomPlot.DetermineMenuEnabledness
  5244.   Description: Sets the Enabledness of Axis-related menus
  5245.        Author: Mat Ballard
  5246.  Date created: 04/17/2000
  5247. Date modified: 04/17/2000 by Mat Ballard
  5248.       Purpose: menu management
  5249.  Known Issues: called from TPlotMenu.HandleClunk
  5250.                Because we have added a "Reopen" sub-submenu, we have to
  5251.                kludge and add "1" to the index of all mnuFile menuitems.
  5252.  ------------------------------------------------------------------------------}
  5253. procedure TCustomPlot.DetermineMenuEnabledness(TheMenu: TMenu);
  5254. begin
  5255.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuPaste)].Enabled :=
  5256.     CanPaste;
  5257.  
  5258.   SetSeriesEnabledness(TheMenu);
  5259.  
  5260. {Note Reopen kludge: "1+"}
  5261.   TheMenu.Items[Ord(mnuFile)].Items[1+Ord(mnuClearOverlays)].Enabled :=
  5262.     (FirstOverlay >= 0);
  5263.  
  5264.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteY2Axis)].Enabled :=
  5265.     (FAxisList.Count > 2);
  5266.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuMoveNotePointer)].Enabled :=
  5267.     (NoteCount > 0);
  5268.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteNote)].Enabled :=
  5269.     (NoteCount > 0);
  5270.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditFont)].Enabled := TRUE;
  5271.  
  5272.   TheMenu.Items[Ord(mnuView)].Items[Ord(mnuHide)].Enabled := TRUE;
  5273.   TheMenu.Items[Ord(mnuView)].Items[Ord(mnuLegend)].Enabled :=
  5274.     (FSeriesList.Count > 1);
  5275.   TheMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].Enabled :=
  5276.     FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].Enabled;
  5277. end;
  5278.  
  5279. {------------------------------------------------------------------------------
  5280.     Procedure: TCustomPlot.SetSeriesEnabledness
  5281.   Description: Sets the Enabledness of Axis-related menus
  5282.        Author: Mat Ballard
  5283.  Date created: 04/17/2000
  5284. Date modified: 04/17/2000 by Mat Ballard
  5285.       Purpose: menu management
  5286.  Known Issues:
  5287.  ------------------------------------------------------------------------------}
  5288. procedure TCustomPlot.SetSeriesEnabledness(TheMenu: TMenu);
  5289. begin
  5290. {Note Reopen kludge: "1+"}
  5291.   TheMenu.Items[Ord(mnuFile)].Items[1+Ord(mnuSave)].Enabled :=
  5292.     (FSeriesList.TotalNoPts > 0) and FSeriesList.DataChanged;
  5293.   TheMenu.Items[Ord(mnuFile)].Items[1+Ord(mnuSaveAs)].Enabled :=
  5294.     (FSeriesList.TotalNoPts > 0);
  5295.  
  5296.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuNearestPoint)].Enabled :=
  5297.     (FSeriesList.TotalNoPts > 0);
  5298.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressAllSeries)].Enabled :=
  5299.     (FSeriesList.TotalNoPts > 20);
  5300.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractAllSeries)].Enabled :=
  5301.     (FSeriesList.TotalNoPts > 20);
  5302.  
  5303.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopyHTML)].Enabled :=
  5304.     (FSeriesList.TotalNoPts > 0);
  5305.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCopySeries)].Enabled :=
  5306.     (FSeriesList.TotalNoPts > 0);
  5307.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplaceDiv)].Enabled :=
  5308.     (FSeriesList.TotalNoPts > 0);
  5309.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDisplace)].Enabled :=
  5310.     (FSeriesList.TotalNoPts > 0);
  5311.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuResetDisplacement)].Enabled :=
  5312.     (FSeriesList.TotalNoPts > 0);
  5313. {NewSeries means that this divider is now always visible:
  5314.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeriesDiv)].Enabled :=
  5315.     (FSeriesList.TotalNoPts > 0);}
  5316.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuCloneSeries)].Enabled :=
  5317.     (FSeriesList.TotalNoPts > 0);
  5318.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditPoint)].Enabled :=
  5319.     (FSeriesList.TotalNoPts > 0);
  5320.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditData)].Enabled :=
  5321.     (FSeriesList.TotalNoPts > 0);
  5322.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuEditSeries)].Enabled :=
  5323.     (FSeriesList.TotalNoPts > 0);
  5324.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuDeleteSeries)].Enabled :=
  5325.     (FSeriesList.TotalNoPts > 0);
  5326.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuLinearize)].Enabled :=
  5327.     (FSeriesList.TotalNoPts > 0);
  5328.   TheMenu.Items[Ord(mnuEdit)].Items[Ord(mnuZero)].Enabled :=
  5329.     (FSeriesList.TotalNoPts > 0);
  5330.  
  5331.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverageDiv)].Enabled :=
  5332.     (FSeriesList.TotalNoPts > 0);
  5333.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalcAverage)].Enabled :=
  5334.     (FSeriesList.TotalNoPts > 0);
  5335.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCompressSeries)].Enabled :=
  5336.      (FSeriesList.TotalNoPts > 20);
  5337.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuContractSeries)].Enabled :=
  5338.      (FSeriesList.TotalNoPts > 20);
  5339.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCubicSpline)].Enabled :=
  5340.     (FSeriesList.TotalNoPts > 0);
  5341.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuHighs)].Enabled :=
  5342.     (FSeriesList.TotalNoPts > 0);
  5343.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuMovingAverage)].Enabled :=
  5344.     (FSeriesList.TotalNoPts > 0);
  5345.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSmoothSeries)].Enabled :=
  5346.     (FSeriesList.TotalNoPts > 0);
  5347.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuSortSeries)].Enabled :=
  5348.     (FSeriesList.TotalNoPts > 0);
  5349.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuCalculusDiv)].Enabled :=
  5350.     (FSeriesList.TotalNoPts > 0);
  5351.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuDifferentiate)].Enabled :=
  5352.     (FSeriesList.TotalNoPts > 0);
  5353.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegrate)].Enabled :=
  5354.     (FSeriesList.TotalNoPts > 0);
  5355.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuIntegral)].Enabled :=
  5356.     (FSeriesList.TotalNoPts > 0);
  5357.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFitDiv)].Enabled :=
  5358.     (FSeriesList.TotalNoPts > 0);
  5359.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuLineOfBestFit)].Enabled :=
  5360.     (FSeriesList.TotalNoPts > 0);
  5361.   TheMenu.Items[Ord(mnuCalc)].Items[Ord(mnuTwoRegionLineOfBestFit)].Enabled :=
  5362.     (FSeriesList.TotalNoPts > 0);
  5363.   {$IFDEF FUNCTIONS}
  5364.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunctionDiv)].Visible := (FSeriesList.Count > 0);
  5365.   FPlotPopUpMenu.Items[Ord(mnuCalc)].Items[Ord(mnuFunction)].Visible := (FSeriesList.Count > 0);
  5366.   {$ENDIF}
  5367. end;
  5368. {$ENDIF}
  5369.  
  5370. {------------------------------------------------------------------------------
  5371.     Procedure: SwapEnds
  5372.   Description: Swaps the selection's Left-Right and Top-Bottom if needed
  5373.        Author: Mat Ballard
  5374.  Date created: 12/1/1999
  5375. Date modified: 02/25/2000 by Mat Ballard
  5376.       Purpose: manageing region selections
  5377.  Known Issues:
  5378.  ------------------------------------------------------------------------------}
  5379. procedure TCustomPlot.SwapEnds;
  5380. var
  5381.   iX: Integer;
  5382. begin
  5383. {swap Left and Right:}
  5384.   if (Selection.Left > Selection.Right) then
  5385.   begin
  5386.     iX := Selection.Left;
  5387.     Selection.Left := Selection.Right;
  5388.     Selection.Right := iX;
  5389.   end;
  5390.  
  5391. {swap Top and Bottom:}
  5392.   if (Selection.Top > Selection.Bottom) then
  5393.   begin
  5394.     iX := Selection.Top;
  5395.     Selection.Top := Selection.Bottom;
  5396.     Selection.Bottom := iX;
  5397.   end;
  5398. end;
  5399.  
  5400. {------------------------------------------------------------------------------
  5401.     Procedure: SetResult
  5402.   Description: Performs calculations on Screen Data
  5403.        Author: Mat Ballard
  5404.  Date created: 12/1/1999
  5405. Date modified: 02/25/2000 by Mat Ballard
  5406.       Purpose: Finishes off Line of Best Fit determinations
  5407.  Known Issues:
  5408.  ------------------------------------------------------------------------------}
  5409. procedure TCustomPlot.SetResult(
  5410.   Slope,
  5411.   Intercept,
  5412.   Rsq: Single);
  5413. begin
  5414.   if (pSeries.XAxis.LogScale) then
  5415.     FResult.Caption := 'Ln(' + pSeries.XAxis.Title.Caption + ')  =  '
  5416.    else
  5417.     FResult.Caption := pSeries.XAxis.Title.Caption + '  =  ';
  5418.   FResult.Caption := FResult.Caption + FloatToStrF(Intercept, ffGeneral, 5, 3) + ' + ';
  5419.   if (pSeries.XAxis.LogScale) then
  5420.     FResult.Caption := FResult.Caption + FloatToStrF(Slope, ffGeneral, 5, 3) +
  5421.       ' ╫ ' + sLn + '(' + pSeries.YAxis.Title.Caption + '),  ' + sRSquare + ' = '
  5422.    else
  5423.     FResult.Caption := FResult.Caption + FloatToStrF(Slope, ffGeneral, 5, 3) +
  5424.       ' ╫ ' + pSeries.YAxis.Title.Caption + ', ' + sRSquare + ' = ';
  5425.   FResult.Caption := FResult.Caption + FloatToStrF(Rsq, ffGeneral, 5, 3);
  5426.   ClipBoard.AsText := FResult.Caption;
  5427.   FResult.Font.Color := pSeries.Pen.Color;
  5428.   FResult.MoveTo(Selection.Left, Selection.Top);
  5429.   FResult.Visible := TRUE;
  5430. end;
  5431.  
  5432. {------------------------------------------------------------------------------
  5433.     Procedure: TCustomPlot.MouseTimeOut
  5434.   Description: responds to the mouse button being held down
  5435.        Author: Mat Ballard
  5436.  Date created: 12/1/1999
  5437. Date modified: 02/25/2000 by Mat Ballard
  5438.       Purpose: Frees the timer, identifies the clicked object, outlines it, and prepares to move it
  5439.  Known Issues:
  5440.  ------------------------------------------------------------------------------}
  5441. procedure TCustomPlot.MouseTimeOut(
  5442.   Sender: TObject);
  5443. {If this is fired, then the user has held the mouse still for one second
  5444.  on a screen object: this is a cue for a move.}
  5445. begin
  5446.   MouseTimer.Enabled := FALSE;
  5447.  
  5448.   if (ClickedObjectType = soNone) then exit;
  5449.  
  5450.   if (FScreenJob = sjTouchNotePointer) then
  5451.   begin
  5452. {$IFDEF COMPILER3_UP}
  5453.     Screen.Cursor := crScope;
  5454. {$ENDIF}
  5455.     FScreenJob := sjMoveNotePointer;
  5456.   end
  5457.   else
  5458.   begin
  5459.     FScreenJob := sjDrag;
  5460. {$IFDEF COMPILER3_UP}
  5461.     Screen.Cursor := crHandPoint;
  5462. {$ENDIF}
  5463.     if (ClickedObjectType = soSeries) then
  5464.     begin
  5465.       pSeries.Outline(Self.Canvas, FPlotType, FOutlineWidth);
  5466.     end
  5467.     else
  5468.     begin
  5469. {This is fascinating: the following call attempts to assign all the TAxis
  5470.  properties of pClickedObject to Selection - which of course pukes:
  5471.     Selection.Assign(TRectangle(pClickedObject));
  5472.  So we have to assign position manually:}
  5473.       if (pClickedObject <> nil) then
  5474.       begin
  5475.         if (pClickedObject = FZAxis) then
  5476.           Selection.SetNewGeometry(Point(
  5477.             FZAxis.Left,
  5478.             FZAxis.Top),
  5479.             FZAxis.Angle,
  5480.             FZAxis.Length,
  5481.             FZAxis.Width div 4)
  5482.          else
  5483.           Selection.SetNewGeometry(Point(
  5484.             TRectangle(pClickedObject).Left,
  5485.             TRectangle(pClickedObject).Top + TRectangle(pClickedObject).Height div 2),
  5486.             90,
  5487.             TRectangle(pClickedObject).Width,
  5488.             TRectangle(pClickedObject).Height);
  5489.       end;
  5490.  
  5491.       OutlineTheClickedObject;
  5492.     end;
  5493.   end; {sjTouchNote}
  5494. end;
  5495.  
  5496. {------------------------------------------------------------------------------
  5497.     Procedure: TCustomPlot.GetTheClickedObject
  5498.   Description: identifies the object(s) that was clicked on
  5499.        Author: Mat Ballard
  5500.  Date created: 12/1/1999
  5501. Date modified: 02/25/2000 by Mat Ballard
  5502.       Purpose: sets ClickedObjectType and SecondClickedObjectType, and TheSeries if it was a Axis.
  5503.  Known Issues:
  5504.  ------------------------------------------------------------------------------}
  5505. procedure TCustomPlot.GetTheClickedObject(
  5506.   X,
  5507.   Y: Integer);
  5508. var
  5509.   i: Integer;
  5510.   MinDistance: Single;
  5511.   ANote: TNote;
  5512.   TheRect: TRect;
  5513. begin
  5514.   pClickedObject := nil;
  5515.   pSecondClickedObject := nil;
  5516.   ClickedObjectType := soNone;
  5517.  
  5518. {page control while zoomed in ?}  
  5519.   if (FPageButtons[0] <> nil) then
  5520.   begin
  5521.     if ((X > Self.Width - 3*FPageButtons[0].Width) and
  5522.         (Y > Self.Height - 2*FPageButtons[0].Height)) then
  5523.     begin
  5524. { x2x
  5525.   031  is the layout:}
  5526.       if (Y > Self.Height - FPageButtons[0].Height) then
  5527.       begin
  5528.         if (X < Self.Width - 2*FPageButtons[0].Width) then
  5529.           PageButtonClick(0)
  5530.         else if (X < Self.Width - FPageButtons[0].Width) then
  5531.           PageButtonClick(3)
  5532.         else
  5533.           PageButtonClick(1);
  5534.       end
  5535.       else
  5536.       begin
  5537.         if ((X >= Self.Width - 2*FPageButtons[0].Width) and
  5538.             (X < Self.Width - FPageButtons[0].Width)) then
  5539.           PageButtonClick(2);  
  5540.       end;
  5541.     end;
  5542.   end;
  5543.  
  5544.   for i := 1 to ScreenObjectList.Count-1 do
  5545.   begin
  5546. {identify the clicked-on object:}
  5547.     if (ScreenObjectList.Items[i] <> nil) then
  5548.     begin
  5549.       if (TRectangle(ScreenObjectList.Items[i]).ClickedOn(X, Y)) then
  5550.       begin
  5551.         if (pClickedObject = nil) then
  5552.         begin
  5553.           pClickedObject := ScreenObjectList.Items[i];
  5554.           ClickedObjectType := TObjectType(TRectangle(pClickedObject).Tag);
  5555.           ClickedObjectOffset.x := X - TRectangle(pClickedObject).Left;
  5556.           ClickedObjectOffset.y := Y - TRectangle(pClickedObject).Top;
  5557.           if ((ClickedObjectType = soXAxis) or
  5558.               (ClickedObjectType = soYAxis) or
  5559.               (ClickedObjectType = soZAxis)) then
  5560.           begin
  5561.             pAxis := TAxis(pClickedObject);
  5562.             TheAxis := FAxisList.IndexOf(pAxis);
  5563.           end;
  5564.         end
  5565.         else
  5566.         begin
  5567. {there are two objects under the mouse: usually an axis and a border:}
  5568.           pSecondClickedObject := ScreenObjectList.Items[i];
  5569.           SecondClickedObjectType := TObjectType(TRectangle(pSecondClickedObject).Tag);
  5570.           exit;
  5571.         end;
  5572.       end;
  5573.     end; {clicked on object i}
  5574.   end; {for}
  5575.  
  5576.   if (ClickedObjectType = soLegend) then
  5577.   begin
  5578.     FLegend.GetHit(X, Y, TheRect);
  5579.   end;
  5580.  
  5581.   if (ClickedObjectType = soNone) then
  5582.   begin
  5583. {was it a note end ?}
  5584.     for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  5585.     begin
  5586.       if (TObject(ScreenObjectList.Items[i]) is TNote) then
  5587.       begin
  5588.         ANote := TNote(ScreenObjectList.Items[i]);
  5589.         if ((Abs(ANote.ArrowLeft - X) < FOutlineWidth) or
  5590.             (Abs(ANote.ArrowTop - Y) < FOutlineWidth)) then
  5591.         begin
  5592.           ClickedObjectType := soNote;
  5593.           pClickedObject := ANote;
  5594.           FScreenJob := sjTouchNotePointer;
  5595.         end;
  5596.       end;
  5597.     end;
  5598.   end;
  5599.  
  5600. {If nothing yet clicked on ...}
  5601.   if (ClickedObjectType = soNone) then
  5602.   begin
  5603.     if ((FPlotType = ptXY) or
  5604.         (FPlotType = ptError) or
  5605.         (FPlotType = ptMultiple) or
  5606.         (FPlotType = ptBubble) or
  5607.         (FPlotType = ptColumn) or
  5608.         (FPlotType = ptStack) or
  5609.         (FPlotType = ptNormStack) or
  5610.         (FPlotType = ptPie)) then
  5611.     begin
  5612. {was it a Series ?}
  5613.       ThePointNumber := FSeriesList.GetNearestPoint(
  5614.         FPlotType,
  5615.         FColumnGap,
  5616.         X, Y, //Selection.Left, Selection.Top,
  5617.         TheSeries,
  5618.         MinDistance,
  5619.         pSeries);
  5620. {give it a wide hit range:}
  5621.       if (MinDistance < (FOutlineWidth)) then
  5622.       begin
  5623.         ClickedObjectType := soSeries;
  5624.         if (FPlotType <= ptBubble) then
  5625.           pSeries.GenerateXYOutline;
  5626.       end;
  5627.     end; {FPlotType}
  5628.   end; {ClickedObjectType = soNone}
  5629. end;
  5630.  
  5631. {------------------------------------------------------------------------------
  5632.     Procedure: TCustomPlot.ProcessClickedObject
  5633.   Description: Adjusts the geometry of a moved (clicked and dragged) object
  5634.        Author: Mat Ballard
  5635.  Date created: 12/1/1999
  5636. Date modified: 02/25/2000 by Mat Ballard
  5637.       Purpose: sets appropriate property(ies) of the object that has been manipulated on screen
  5638.  Known Issues:
  5639.  ------------------------------------------------------------------------------}
  5640. procedure TCustomPlot.ProcessClickedObject(
  5641.   pObject: Pointer;
  5642.   TheObjectType: TObjectType);
  5643. var
  5644.   NewMousePoint: TPoint;
  5645. begin
  5646.   case TheObjectType of
  5647.     soTitle:
  5648.       begin
  5649.         if (Selection.Left = FBorder.Left) then
  5650.           FTitle.Alignment := taLeftJustify
  5651.          else if (Selection.Right = FBorder.Right) then
  5652.           FTitle.Alignment := taRightJustify
  5653.          else
  5654.           FTitle.Alignment := taCenter;
  5655.         if (Selection.Top < FBorder.MidY) then
  5656.           FTitle.Orientation := orLeft
  5657.          else
  5658.           FTitle.Orientation := orRight;
  5659.       end;
  5660.  
  5661.     soLegend:
  5662.       begin
  5663.         FLegend.MoveTo(Selection.Left, Selection.Top);
  5664.       end;
  5665.  
  5666.     soResult:
  5667.       begin
  5668.         FResult.MoveTo(Selection.Left, Selection.Top);
  5669.       end;
  5670.  
  5671.     soXAxis:
  5672.       begin
  5673.         FXAxis.Intercept := FYAxis.YofF(Selection.MidY);
  5674.       end;
  5675.  
  5676.     soZAxis:
  5677.       begin
  5678.         FZAxis.Intercept := FXAxis.XofF(Selection.Origin.x);
  5679.         FZAxis.ZInterceptY := FYAxis.YofF(Selection.Origin.y);
  5680.       end;
  5681.  
  5682.     soXAxisTitle:
  5683.       begin
  5684.         if (Selection.Left = FBorder.Left) then
  5685.           FXAxis.Title.Alignment := taLeftJustify
  5686.          else if (Selection.Right = FBorder.Right) then
  5687.           FXAxis.Title.Alignment := taRightJustify
  5688.          else
  5689.           FXAxis.Title.Alignment := taCenter;
  5690.         if (Selection.Top < FXAxis.MidY) then
  5691.           FXAxis.Title.Orientation := orLeft
  5692.          else
  5693.           FXAxis.Title.Orientation := orRight;
  5694.       end;
  5695.     soXAxisLabel:
  5696.       begin
  5697.         if (Selection.Top < FXAxis.MidY) then
  5698.           FXAxis.TickDirection := orLeft
  5699.          else
  5700.           FXAxis.TickDirection := orRight;
  5701.       end;
  5702.  
  5703.     soYAxis:
  5704.       begin
  5705.         TAxis(pObject).Intercept := FXAxis.XofF(Selection.MidX);
  5706.         Resize;
  5707.       end;
  5708.     soYAxisTitle:
  5709.       begin
  5710.         if (Selection.Left < TAxis(TTitle(pObject).Owner).MidX) then
  5711.           TTitle(pObject).Orientation := orLeft
  5712.          else
  5713.           TTitle(pObject).Orientation := orRight;
  5714.         if (Selection.Top = FBorder.Top) then
  5715.           TTitle(pObject).Alignment := taRightJustify
  5716.          else if (Selection.Bottom = FBorder.Bottom) then
  5717.           TTitle(pObject).Alignment := taLeftJustify
  5718.          else
  5719.           TTitle(pObject).Alignment := taCenter;
  5720.       end;
  5721.     soYAxisLabel:
  5722.       begin
  5723.         if (Selection.Left < TAxis(TAxisLabel(pObject).Owner).MidX) then
  5724.           TAxis(TAxisLabel(pObject).Owner).TickDirection := orLeft
  5725.          else
  5726.           TAxis(TAxisLabel(pObject).Owner).TickDirection := orRight;
  5727.       end;
  5728.  
  5729.     soLeftBorder: FBorder.Left := Selection.MidX;
  5730.     soRightBorder: FBorder.Right := Selection.MidX;
  5731.     soTopBorder: FBorder.Top := Selection.MidY;
  5732.     soBottomBorder: FBorder.Bottom := Selection.MidY;
  5733.  
  5734.     soNote:
  5735.       begin
  5736.         TNote(pObject).MoveTo(Selection.Left, Selection.Top);
  5737. {now lets move the note pointer:}
  5738. {$IFDEF COMPILER3_UP}
  5739.         Screen.Cursor := crScope;
  5740. {$ENDIF}
  5741.         FScreenJob := sjMoveNotePointer;
  5742.         NewMousePoint.x := TNote(pObject).ArrowLeft;
  5743.         NewMousePoint.Y := TNote(pObject).ArrowTop;
  5744.         ClientToScreen(NewMousePoint);
  5745. {$IFDEF BCB}
  5746.         SetCursorPos(NewMousePoint.x, NewMousePoint.y);
  5747. {$ELSE} {BCB doesn't like:}
  5748.         Mouse.CursorPos := ClientToScreen(NewMousePoint);
  5749. {$ENDIF}
  5750.         exit;
  5751.       end;
  5752.  
  5753.     soSeries: { already moved by direct change of DeltaX and DeltaY properties}
  5754.       begin
  5755.  
  5756.       end;
  5757.   end; {case TheObjectType}
  5758.   ZeroScreenStuff;
  5759.   DoStyleChange(Self);
  5760. end;
  5761.  
  5762. {------------------------------------------------------------------------------
  5763.     Procedure: TCustomPlot.OutlineTheClickedObject
  5764.   Description: Outlines The Clicked Object
  5765.        Author: Mat Ballard
  5766.  Date created: 12/1/1999
  5767. Date modified: 02/25/2000 by Mat Ballard
  5768.       Purpose: gives the user a guide to what they are manipulating with the mouse
  5769.  Known Issues:
  5770.  ------------------------------------------------------------------------------}
  5771. procedure TCustomPlot.OutlineTheClickedObject;
  5772. begin
  5773.   if (ClickedObjectType = soSeries) then
  5774.     pSeries.Outline(Self.Canvas, FPlotType, FOutlineWidth)
  5775.    else
  5776.     Selection.Outline(Self.Canvas);
  5777. end;
  5778.  
  5779. {------------------------------------------------------------------------------
  5780.     Procedure: TCustomPlot.MoveTheClickedObjectTo
  5781.   Description: This moves the clicked object outline TO (X, Y)
  5782.        Author: Mat Ballard
  5783.  Date created: 12/1/1999
  5784. Date modified: 02/25/2000 by Mat Ballard
  5785.       Purpose: gives the user a guide to what they are moving with the mouse
  5786.  Known Issues:
  5787.  ------------------------------------------------------------------------------}
  5788. procedure TCustomPlot.MoveTheClickedObjectTo(
  5789.   X,
  5790.   Y: Integer);
  5791. begin
  5792.   if ((Selection.Left = X) and (Selection.Top = Y)) then exit;
  5793.  
  5794. {erase the old outline:}
  5795.   OutlineTheClickedObject;
  5796.  
  5797. {re-initialize the Selection:}
  5798.   Selection.MoveTo(X, Y);
  5799.  
  5800. {create the new outline:}
  5801.   OutlineTheClickedObject;
  5802. end;
  5803.  
  5804. {------------------------------------------------------------------------------
  5805.     Procedure: TCustomPlot.StretchTheClickedObjectTo
  5806.   Description: Stretch The Clicked Object To
  5807.        Author: Mat Ballard
  5808.  Date created: 12/1/1999
  5809. Date modified: 02/25/2000 by Mat Ballard
  5810.       Purpose: gives the user a guide to what they are selecting with the mouse
  5811.  Known Issues:
  5812.  ------------------------------------------------------------------------------}
  5813. procedure TCustomPlot.StretchTheClickedObjectTo(
  5814.   X,
  5815.   Y: Integer);
  5816. {This moves the far (right, bottom) point of the Stretched object outline TO (X, Y).}
  5817. begin
  5818.   if ((Selection.Right = X) and (Selection.Bottom = Y)) then
  5819.     exit;
  5820.  
  5821. {erase the old outline:}
  5822.   //OutlineTheSelection;
  5823.   Selection.Outline(Canvas);
  5824.  
  5825. {re-initialize the Selection:}
  5826.   Selection.Right := X;
  5827.   Selection.Bottom := Y;
  5828.  
  5829. {create the new outline:}
  5830.   //OutlineTheSelection;
  5831.   Selection.Outline(Canvas);
  5832. end;
  5833.  
  5834. {------------------------------------------------------------------------------
  5835.     Procedure: MoveTheClickedObjectClick
  5836.   Description: deals with the end of a screen operation at MouseUp
  5837.        Author: Mat Ballard
  5838.  Date created: 12/1/1999
  5839. Date modified: 02/25/2000 by Mat Ballard
  5840.       Purpose: Processes the first Clicked Object
  5841.  Known Issues:
  5842.  ------------------------------------------------------------------------------}
  5843. procedure TCustomPlot.MoveTheClickedObjectClick(
  5844.   Sender: TObject);
  5845. begin
  5846.   ProcessClickedObject(pClickedObject, ClickedObjectType);
  5847. end;
  5848.  
  5849. {------------------------------------------------------------------------------
  5850.     Procedure: MoveSecondClickedObjectClick
  5851.   Description: deals with the end of a screen operation at MouseUp
  5852.        Author: Mat Ballard
  5853.  Date created: 12/1/1999
  5854. Date modified: 02/25/2000 by Mat Ballard
  5855.       Purpose: Processes the SECOND Clicked Object
  5856.  Known Issues:
  5857.  ------------------------------------------------------------------------------}
  5858. procedure TCustomPlot.MoveSecondClickedObjectClick(
  5859.   Sender: TObject);
  5860. begin
  5861.   ProcessClickedObject(pSecondClickedObject, SecondClickedObjectType);
  5862. end;
  5863.  
  5864. {General public methods -----------------------------------------------------}
  5865. {------------------------------------------------------------------------------
  5866.     Procedure: TCustomPlot.AddData
  5867.   Description: Add data to the graph
  5868.        Author: Mat Ballard
  5869.  Date created: 12/1/1999
  5870. Date modified: 02/25/2000 by Mat Ballard
  5871.       Purpose: adds data to all Axis simultaneously, avoiding re-drawing the data 
  5872.  Known Issues:
  5873.  ------------------------------------------------------------------------------}
  5874. procedure TCustomPlot.AddData(
  5875.   NoPoints: Integer;
  5876.   XYArray: pXYArray);
  5877. var
  5878.   i: Integer;
  5879. begin
  5880.   if ((NoPoints > 0) and (NoPoints <= FSeriesList.Count)) then
  5881.   begin
  5882.     if (FDisplayMode <> dmHistory) then
  5883.     begin
  5884.       for i := 0 to NoPoints-1 do
  5885.       begin
  5886.         TSeries(FSeriesList.Items[i]).AddDrawPoint(XYArray^[i].X, XYArray^[i].Y, Canvas);
  5887.       end;
  5888.     end
  5889.     else
  5890.     begin
  5891.       case FPlotType of
  5892.         ptXY:
  5893.           begin
  5894. {erase the old curve:}
  5895.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5896.             for i := 0 to NoPoints-1 do
  5897.             begin
  5898.               TSeries(FSeriesList.Items[i]).AddPoint(XYArray^[i].X, XYArray^[i].Y, FALSE, FALSE);
  5899.             end;
  5900. {draw the new one:}
  5901.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5902.           end;
  5903.         ptMultiple:
  5904.           begin
  5905. {erase the old curve:}
  5906.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5907.             Canvas.Pen.Assign(FMultiplePen);
  5908.             FSeriesList.DrawHistoryMultiple(Canvas, FMultiplicity);
  5909.             for i := 0 to NoPoints-1 do
  5910.             begin
  5911.               TSeries(FSeriesList.Items[i]).AddPoint(XYArray^[i].X, XYArray^[i].Y, FALSE, FALSE);
  5912.             end;
  5913. {draw the new one:}
  5914.             FSeriesList.DrawHistory(Canvas, FDisplayHistory);
  5915.             Canvas.Pen.Assign(FMultiplePen);
  5916.             FSeriesList.DrawHistoryMultiple(Canvas, FMultiplicity);
  5917.           end;
  5918.         ptColumn:
  5919.           begin
  5920.           end;
  5921.         {ptPipeLine:
  5922.           begin
  5923.           end;}
  5924.       end;
  5925.     end;
  5926.   end
  5927.   else
  5928.     EMathError.CreateFmt(sAddDataError, [FSeriesList.Count]);
  5929. end;
  5930.  
  5931. {------------------------------------------------------------------------------
  5932.      Function: TCustomPlot.AddSeries
  5933.   Description: wrapper for TSeriesList.Add
  5934.        Author: Mat Ballard
  5935.  Date created: 12/1/1999
  5936. Date modified: 02/25/2000 by Mat Ballard
  5937.       Purpose: Adds a new, empty data Series to the graph
  5938.  Return Value: the Index of the new Series
  5939.  Known Issues:
  5940.  ------------------------------------------------------------------------------}
  5941. function TCustomPlot.AddSeries(
  5942.   XSeriesIndex: Integer): Integer;
  5943. begin
  5944.   AddSeries := FSeriesList.Add(XSeriesIndex);
  5945. end;
  5946.  
  5947. {------------------------------------------------------------------------------
  5948.      Function: TCustomPlot.AddExternal
  5949.   Description: wrapper for TSeriesList.AddExternal
  5950.        Author: Mat Ballard
  5951.  Date created: 12/1/1999
  5952. Date modified: 02/25/2000 by Mat Ballard
  5953.       Purpose: Adds a new data Series that is maintained elsewhere to the graph
  5954.  Known Issues:
  5955.  ------------------------------------------------------------------------------}
  5956. function TCustomPlot.AddExternalSeries(
  5957.   XPointer,
  5958.   YPointer: pSingleArray;
  5959.   NumberOfPoints: Integer): Integer;
  5960. begin
  5961.   AddExternalSeries := FSeriesList.AddExternal(XPointer, YPointer, NumberOfPoints);
  5962. end;
  5963.  
  5964. {------------------------------------------------------------------------------
  5965.      Function: TCustomPlot.AddInternal
  5966.   Description: wrapper for TSeriesList.AddInternal
  5967.        Author: Mat Ballard
  5968.  Date created: 12/1/1999
  5969. Date modified: 02/25/2000 by Mat Ballard
  5970.       Purpose: Adds a new data Series from elsewhere to the graph, and saves it internally
  5971.  Known Issues:
  5972.  ------------------------------------------------------------------------------}
  5973. function TCustomPlot.AddInternalSeries(
  5974.   XPointer,
  5975.   YPointer: pSingleArray; 
  5976.   NumberOfPoints: Integer): Integer;
  5977. begin
  5978.   AddInternalSeries := FSeriesList.AddInternal(XPointer, YPointer, NumberOfPoints);
  5979. end;
  5980.  
  5981. {------------------------------------------------------------------------------
  5982.     Procedure: TCustomPlot.CloneSeries
  5983.   Description: wrapper for TSeriesList.CloneSeries
  5984.        Author: Mat Ballard
  5985.  Date created: 12/1/1999
  5986. Date modified: 02/25/2000 by Mat Ballard
  5987.       Purpose: Clones the specified Series
  5988.  Known Issues:
  5989.  ------------------------------------------------------------------------------}
  5990. function TCustomPlot.CloneSeries(
  5991.   TheSeries: Integer): Integer;
  5992. begin
  5993.   CloneSeries := FSeriesList.CloneSeries(TheSeries);
  5994. end;
  5995.  
  5996. {------------------------------------------------------------------------------
  5997.     Procedure: TCustomPlot.DeleteSeries
  5998.   Description: wrapper for TSeriesList.DeleteSeries
  5999.        Author: Mat Ballard
  6000.  Date created: 12/1/1999
  6001. Date modified: 02/25/2000 by Mat Ballard
  6002.       Purpose: Deletes the specified Series
  6003.  Known Issues:
  6004.  ------------------------------------------------------------------------------}
  6005. procedure TCustomPlot.DeleteSeries(
  6006.   Index: Integer);
  6007. begin
  6008.   FSeriesList.DeleteSeries(Index, not(csDesigning in ComponentState));
  6009. end;
  6010.  
  6011. {Responding to user (right) click menus -------------------------------------}
  6012. {------------------------------------------------------------------------------
  6013.     Procedure: TCustomPlot.CopyClick
  6014.   Description: The public copying method
  6015.        Author: Mat Ballard
  6016.  Date created: 12/1/1999
  6017. Date modified: 02/25/2000 by Mat Ballard
  6018.       Purpose: copies the graph to the clipboard, in all formats simultaneously
  6019.  Known Issues:
  6020.  ------------------------------------------------------------------------------}
  6021. procedure TCustomPlot.CopyClick(
  6022.   Sender: TObject);
  6023. begin
  6024. {$IFDEF MSWINDOWS}
  6025.   ClipBoardFormatForHTML := RegisterClipboardFormat('cfHTML');
  6026.   ClipBoard.Open;
  6027.   try
  6028. {copy all three formats to the clipboard at once:}
  6029.     CopyText;
  6030.     CopyHTML(ClipBoardFormatForHTML);
  6031.     CopyBitmap;
  6032.     CopyDrawing(TRUE);
  6033.   finally
  6034.     ClipBoard.Close;
  6035.   end;
  6036. {$ENDIF}
  6037. {$IFDEF LINUX}
  6038.   CopyText;
  6039.   CopyHTML(ClipBoardFormatForHTML);
  6040.   CopyBitmap;
  6041. {$ENDIF}
  6042. end;
  6043.  
  6044. {------------------------------------------------------------------------------
  6045.     Procedure: TCustomPlot.HideClick
  6046.   Description: Hides part of the graph
  6047.        Author: Mat Ballard
  6048.  Date created: 12/1/1999
  6049. Date modified: 02/25/2000 by Mat Ballard
  6050.       Purpose: makes the selected object invisible
  6051.  Known Issues:
  6052.  ------------------------------------------------------------------------------}
  6053. procedure TCustomPlot.HideClick(
  6054.   Sender: TObject);
  6055. begin
  6056.   if (Sender is TPlotMenu) then
  6057.   begin
  6058.     FInstructions.Clear;
  6059.     FInstructions.Add(sHideInstruction);
  6060.     ScreenJob := sjHide;
  6061.     DoStyleChange(Self);
  6062.     exit;
  6063.   end;
  6064.  
  6065.   case ClickedObjectType of
  6066.     soTitle: FTitle.Visible := FALSE;
  6067.     soLegend: FLegend.Visible := FALSE;
  6068.     soResult: FResult.Visible := FALSE;
  6069.     soNote: TNote(pClickedObject).Visible := FALSE;
  6070.     soXAxis: FXAxis.Visible := FALSE;
  6071.     soYAxis: TAxis(pClickedObject).Visible := FALSE;
  6072.     soXAxisTitle: FXAxis.Title.Visible := FALSE;
  6073.     soYAxisTitle: TTitle(pClickedObject).Visible := FALSE;
  6074.     soXAxisLabel: FXAxis.Labels.Visible := FALSE;
  6075.     soYAxisLabel: TAxisLabel(pClickedObject).Visible := FALSE;
  6076.     soSeries: pSeries.Visible := FALSE;
  6077.   end;
  6078.   DoStyleChange(Self);
  6079.   ZeroScreenStuff;
  6080. end;
  6081.  
  6082. {------------------------------------------------------------------------------
  6083.     Procedure: TCustomPlot.PrintClick
  6084.   Description: The public printing method
  6085.        Author: Mat Ballard
  6086.  Date created: 12/1/1999
  6087. Date modified: 02/25/2000 by Mat Ballard
  6088.       Purpose: Print the graph
  6089.  Known Issues: We kludge this one a bit by creating a metafile, then playing it
  6090.                on the printer canvas. It would be nicer to draw directly on the
  6091.                printer canvas.
  6092.  ------------------------------------------------------------------------------}
  6093. procedure TCustomPlot.PrintClick(
  6094.   Sender: TObject);
  6095. var
  6096.   i,
  6097.   Copies: Integer;
  6098.   //Copies: Integer; currently ignored by the Qt dialog
  6099.   PrintBorder: TRect;
  6100. {$IFDEF MSWINDOWS}
  6101.   PrintDialog: TPrintDialog;
  6102.   HorzSizeMM, VertSizeMM: Integer;
  6103. {$ENDIF}
  6104. {$IFDEF LINUX}
  6105.   ThePrinter: TPrinter;
  6106. {$ENDIF}
  6107. begin
  6108. {$IFDEF LINUX}
  6109.   ThePrinter := Printer;
  6110.   ThePrinter.Orientation := FPrintOrientation; 
  6111.   if (ThePrinter.ExecuteSetup) then
  6112.   begin
  6113.     ThePrinter.Title := ExtractFileName(Application.ExeName) + ' - ' + FTitle.Caption;
  6114.     {with ThePrinter do
  6115.     begin
  6116.       ShowMessageFmt(ThePrinter.Printers.Text + #10 +
  6117.         'Copies = %d (%d)' + #10 +
  6118.         'Orientation = %d' + #10 +
  6119.         'PageWidth = %d' + #10 +
  6120.         'PageHeight = %d' + #10 +
  6121.         'Margins = (%d, %d)' + #10 +
  6122.         'XDPI = %d' + #10 +
  6123.         'YDPI = %d' + #10 +
  6124.         'OutputDevice: ' + OutputDevice + #10 +
  6125.         'Title: ' + Title,
  6126.         [Copies, ThePrinter.PrintAdapter.Copies, Ord(Orientation),
  6127.          PageWidth, PageHeight, Margins.cx, Margins.cy, XDPI, YDPI]);
  6128.     end;}
  6129.     if (ThePrinter.Copies < 1) then
  6130.       ThePrinter.Copies := 1;
  6131.  
  6132. {i like 1" borders:}
  6133.     PrintBorder.Left := 1 * ThePrinter.XDPI;
  6134.     PrintBorder.Top := 1 * ThePrinter.YDPI;
  6135.     PrintBorder.Right := ThePrinter.PageWidth - 1 * ThePrinter.XDPI;
  6136.     PrintBorder.Bottom := ThePrinter.PageHeight - 1 * ThePrinter.YDPI;
  6137.  
  6138.     ThePrinter.BeginDoc;
  6139.     for i := 1 to ThePrinter.Copies do
  6140.     begin
  6141.       if (i > 1) then
  6142.         ThePrinter.NewPage;
  6143.       ThePrinter.Canvas.Start(TRUE);
  6144.       ThePrinter.Canvas.StretchDraw(PrintBorder, Self.Drawing);
  6145.       //ThePrinter.PrintAdapter.Canvas.StretchDraw(PrintBorder, Self.Drawing);
  6146.  
  6147.       ThePrinter.Canvas.Pen.Color := clBlack;
  6148.       ThePrinter.Canvas.Pen.Width := 9;
  6149.       ThePrinter.Canvas.Pen.Style := psSolid;
  6150.       ThePrinter.Canvas.MoveTo(PrintBorder.Left, PrintBorder.Top);
  6151.       ThePrinter.Canvas.LineTo(PrintBorder.Right, PrintBorder.Bottom);
  6152.       ThePrinter.Canvas.MoveTo(PrintBorder.Right, PrintBorder.Top);
  6153.       ThePrinter.Canvas.LineTo(PrintBorder.Left, PrintBorder.Bottom);
  6154.  
  6155.       ThePrinter.Canvas.Stop;
  6156.     end;
  6157.     ThePrinter.EndDoc;
  6158.   end;
  6159. {$ENDIF}
  6160.  
  6161. {$IFDEF MSWINDOWS}
  6162.   Printer.Orientation := FPrintOrientation;
  6163.  
  6164.   PrintDialog := TPrintDialog.Create(Self);
  6165.   PrintDialog.Options := [poPrintToFile, poWarning];
  6166.   if (PrintDialog.Execute) then
  6167.   begin
  6168.     if (PrintDialog.Copies > 1) then
  6169.       Copies := PrintDialog.Copies
  6170.      else
  6171.       Copies := 1;
  6172.     Printer.Title := Application.ExeName + ' - ' + FTitle.Caption;
  6173.  
  6174.     HorzSizeMM := GetDeviceCaps(Printer.Handle, HORZSIZE);
  6175.     VertSizeMM := GetDeviceCaps(Printer.Handle, VERTSIZE);
  6176.  
  6177. {Set the margins to 25 mm:}
  6178.     PrintBorder.Left := 25 * (Printer.PageWidth div HorzSizeMM);
  6179.     PrintBorder.Top := 25 * (Printer.PageHeight div VertSizeMM);
  6180.     PrintBorder.Right := Printer.PageWidth - PrintBorder.Left;
  6181.     PrintBorder.Bottom := Printer.PageHeight - PrintBorder.Top;
  6182.  
  6183. {note: the D4 TPrinter has a Copies property, but not all printers support it,
  6184.  so do printing the slow way:}
  6185.     Printer.BeginDoc;
  6186.     for i := 1 to Copies do
  6187.     begin
  6188.       if (i > 1) then
  6189.         Printer.NewPage;
  6190.       Printer.Canvas.StretchDraw(PrintBorder, Self.Drawing);
  6191.     end;
  6192.  
  6193.     Printer.EndDoc;
  6194.     //DoStyleChange(Self);
  6195.   end; {PrintDialog}
  6196.   PrintDialog.Free;
  6197. {$ENDIF}
  6198. end;
  6199.  
  6200. {------------------------------------------------------------------------------
  6201.     Procedure: TCustomPlot.ShowAllClick
  6202.   Description: Shows/reveals all screen objects
  6203.        Author: Mat Ballard
  6204.  Date created: 12/1/1999
  6205. Date modified: 02/25/2000 by Mat Ballard
  6206.       Purpose: makes everything visible.
  6207.  Known Issues:
  6208.  ------------------------------------------------------------------------------}
  6209. procedure TCustomPlot.ShowAllClick(
  6210.   Sender: TObject);
  6211. var
  6212.   i: Integer;
  6213. begin
  6214.   for i := 0 to FSeriesList.Count-1 do
  6215.     TSeries(FSeriesList[i]).Visible := TRUE;
  6216.  
  6217.   for i := 0 to ScreenObjectList.Count-1 do
  6218.     TRectangle(ScreenObjectList.Items[i]).Visible := TRUE;
  6219.  
  6220.   DoStyleChange(Self);
  6221. end;
  6222.  
  6223. {------------------------------------------------------------------------------
  6224.     Procedure: TCustomPlot.PositionClick
  6225.   Description: Where the hell are we ?
  6226.        Author: Mat Ballard
  6227.  Date created: 12/1/1999
  6228. Date modified: 02/25/2000 by Mat Ballard
  6229.       Purpose: Displays (and copies) the current mouse click position, in USER units
  6230.  Known Issues:
  6231.  ------------------------------------------------------------------------------}
  6232. procedure TCustomPlot.PositionClick(
  6233.   Sender: TObject);
  6234. var
  6235.   Msg: String;
  6236. begin
  6237.   if (Sender is TPlotMenu) then
  6238. {came via }
  6239.   begin
  6240.     ScreenJob := sjPosition;
  6241.     Screen.Cursor := crScope;
  6242.     FInstructions.Clear;
  6243.     FInstructions.Add(sPosition1);
  6244.     DoStyleChange(Self);
  6245.   end
  6246.   else
  6247.   begin
  6248.     Msg := Format(sPosition2,
  6249.       [Selection.Left, Selection.Top]) + CRLF +
  6250.         sPosition3 +
  6251.           FXAxis.LabelToStrF(FXAxis.XofF(Selection.Left));
  6252.     if (Length(FXAxis.Title.Units) > 0) then
  6253.       Msg := Msg + ' ' + FXAxis.Title.Units;
  6254.     Msg := Msg + ', ' +
  6255.       FYAxis.LabelToStrF(FYAxis.YofF(Selection.Top));
  6256.     if (Length(FYAxis.Title.Units) > 0) then
  6257.       Msg := Msg + ' ' + FYAxis.Title.Units;
  6258.     Msg := Msg + ').';
  6259.     ShowMessage(Msg);
  6260.     ClipBoard.AsText := Msg;
  6261.     ZeroScreenStuff;
  6262.   end;
  6263. end;
  6264.  
  6265. {------------------------------------------------------------------------------
  6266.     Procedure: TCustomPlot.NearestPointClick
  6267.   Description: Where the hell is it ?
  6268.        Author: Mat Ballard
  6269.  Date created: 12/1/1999
  6270. Date modified: 02/25/2000 by Mat Ballard
  6271.       Purpose: finds the nearest point of the nearest Axis
  6272.  Known Issues:
  6273.  ------------------------------------------------------------------------------}
  6274. procedure TCustomPlot.NearestPointClick(
  6275.   Sender: TObject);
  6276. var
  6277.   NearestiX,
  6278.   NearestiY: Integer;
  6279.   MinDistance: Single;
  6280.   Msg: String;
  6281. begin
  6282.   if (Sender is TPlotMenu) then
  6283. {came via }
  6284.   begin
  6285.     ScreenJob := sjNearestPoint;
  6286.     Screen.Cursor := crX;
  6287.     FInstructions.Clear;
  6288.     FInstructions.Add(sClickNear);
  6289.     DoStyleChange(Self);
  6290.   end
  6291.   else
  6292.   begin
  6293.     ThePointNumber := FSeriesList.GetNearestPoint(
  6294.       FPlotType,
  6295.       FColumnGap,
  6296.       Selection.Left, Selection.Top,
  6297.       TheSeries,
  6298.       MinDistance,
  6299.       pSeries);
  6300.     Msg := sTheNearestPointIs + IntToStr(ThePointNumber) + ' in ' +
  6301.       pSeries.Name + CRLF + sAt + ' (' +
  6302.         FXAxis.LabelToStrF(pSeries.XData^[ThePointNumber]);
  6303.     if (Length(FXAxis.Title.Units) > 0) then
  6304.       Msg := Msg + ' ' + FXAxis.Title.Units;
  6305.     Msg := Msg + ', ' +
  6306.       FYAxis.LabelToStrF(pSeries.YData^[ThePointNumber]);
  6307.     if (Length(FYAxis.Title.Units) > 0) then
  6308.       Msg := Msg + ' ' + FYAxis.Title.Units;
  6309.     Msg := Msg + ').';
  6310.  
  6311.     Canvas.Pen.Color := clRed;
  6312.     Canvas.Pen.Mode := pmNotXOR;
  6313.     Canvas.Pen.Style := psSolid;
  6314.     Canvas.Pen.Width := 2;
  6315.     NearestiX := pSeries.XAxis.FofX(pSeries.XData^[ThePointNumber]);
  6316.     NearestiY := pSeries.YAxis.FofY(pSeries.YData^[ThePointNumber]);
  6317.     Canvas.Ellipse(NearestiX-10, NearestiY-10, NearestiX+10, NearestiY+10);
  6318.  
  6319.     ShowMessage(Msg);
  6320.     ClipBoard.AsText := Msg;
  6321.  
  6322.       {Pen.Color := clBlack;
  6323.       Pen.Mode := pmNotXOR;
  6324.       Pen.Style := psSolid;}
  6325.     Canvas.Ellipse(NearestiX-10, NearestiY-10, NearestiX+10, NearestiY+10);
  6326.  
  6327.     ZeroScreenStuff;
  6328.   end;
  6329. end;
  6330.  
  6331. {------------------------------------------------------------------------------
  6332.     Procedure: TCustomPlot.DeleteSeriesClick
  6333.   Description: wrapper for TSeriesList.DeleteSeries
  6334.        Author: Mat Ballard
  6335.  Date created: 12/1/1999
  6336. Date modified: 02/25/2000 by Mat Ballard
  6337.       Purpose: Deletes the selected Series
  6338.  Known Issues:
  6339.  ------------------------------------------------------------------------------}
  6340. procedure TCustomPlot.DeleteSeriesClick(
  6341.   Sender: TObject);
  6342. begin
  6343.   if (GetSeriesFromUser) then
  6344.   begin
  6345.     FSeriesList.DeleteSeries(TheSeries, not(csDesigning in ComponentState));
  6346.     DoStyleChange(Self);
  6347.   end;
  6348.   ZeroScreenStuff;
  6349. end;
  6350.  
  6351. {------------------------------------------------------------------------------
  6352.     Procedure: TCustomPlot.CopySeriesClick
  6353.   Description: wrapper for TSeriesList.CopySeries
  6354.        Author: Mat Ballard
  6355.  Date created: 12/1/1999
  6356. Date modified: 02/25/2000 by Mat Ballard
  6357.       Purpose: Copies the selected Series (as text)
  6358.  Known Issues:
  6359.  ------------------------------------------------------------------------------}
  6360. procedure TCustomPlot.CopySeriesClick(
  6361.   Sender: TObject);
  6362. begin
  6363.   if (GetSeriesFromUser) then
  6364.     pSeries.CopyToClipBoard;
  6365.   ZeroScreenStuff;
  6366. end;
  6367.  
  6368. {------------------------------------------------------------------------------
  6369.     Procedure: TCustomPlot.NewSeriesClick
  6370.   Description: wrapper for TSeriesList.AddSeries
  6371.        Author: Mat Ballard
  6372.  Date created: 04/16/2001
  6373. Date modified: 04/16/2001 by Mat Ballard
  6374.       Purpose: Adds a new Series
  6375.  Known Issues:
  6376.  ------------------------------------------------------------------------------}
  6377. procedure TCustomPlot.NewSeriesClick(
  6378.   Sender: TObject);
  6379. var
  6380.   Index,
  6381.   TheNewSeries: Integer;
  6382.   pXSeries: TSeries;
  6383.   OptionsDlg: TOptionsDlg;
  6384. begin
  6385.   OptionsDlg := TOptionsDlg.Create(nil);
  6386.  
  6387.   OptionsDlg.FormTitle := sNewSeries1;
  6388.   OptionsDlg.Question := sNewSeries2;
  6389.   OptionsDlg.OptionList.Add(sNewSeries3);
  6390.   for Index := 0 to FSeriesList.Count-1 do
  6391.     OptionsDlg.OptionList.Add(TSeries(FSeriesList.Items[Index]).Name);
  6392.  
  6393.   Index := OptionsDlg.Execute - 1;
  6394.  
  6395.   OptionsDlg.Free;
  6396.  
  6397.   if (Index >= 0) then
  6398.   begin
  6399.     if (Index = 0) then
  6400.     begin
  6401.       TheNewSeries := FSeriesList.Add(-1);
  6402.     end
  6403.     else
  6404.     begin
  6405.       pXSeries := TSeries(FSeriesList.Items[Index]);
  6406.       if (pXSeries.ExternalXSeries) then
  6407.         pXSeries := pXSeries.XDataSeries;
  6408.       Index := FSeriesList.IndexOf(pXSeries);
  6409.       TheNewSeries := FSeriesList.Add(Index);
  6410.     end;
  6411.     TSeries(FSeriesList.Items[TheNewSeries]).EditData(FHelpFile);
  6412.   end;
  6413.   ZeroScreenStuff;
  6414. end;
  6415.  
  6416. {------------------------------------------------------------------------------
  6417.     Procedure: TCustomPlot.CloneSeriesClick
  6418.   Description: wrapper for TSeriesList.CloneSeries
  6419.        Author: Mat Ballard
  6420.  Date created: 12/1/1999
  6421. Date modified: 02/25/2000 by Mat Ballard
  6422.       Purpose: Clones the selected Series
  6423.  Known Issues:
  6424.  ------------------------------------------------------------------------------}
  6425. procedure TCustomPlot.CloneSeriesClick(
  6426.   Sender: TObject);
  6427. begin
  6428.   if (GetSeriesFromUser) then
  6429.   begin
  6430.     FSeriesList.CloneSeries(TheSeries);
  6431.     DoStyleChange(Self);
  6432.   end;
  6433.   ZeroScreenStuff;
  6434. end;
  6435.  
  6436. {------------------------------------------------------------------------------
  6437.     Procedure: TCustomPlot.ModeClick
  6438.   Description: Changes how the graph appears and reacts to new data
  6439.        Author: Mat Ballard
  6440.  Date created: 12/1/1999
  6441. Date modified: 02/25/2000 by Mat Ballard
  6442.       Purpose: sets the DisplayMode property
  6443.  Known Issues:
  6444.  ------------------------------------------------------------------------------}
  6445. procedure TCustomPlot.ModeClick(
  6446.   Sender: TObject);
  6447. var
  6448.   Index: Integer;
  6449.   DisplayHistoryStr: String;
  6450.   OptionsDlg: TOptionsDlg;
  6451. begin
  6452.   OptionsDlg := TOptionsDlg.Create(nil);
  6453.  
  6454.   OptionsDlg.FormTitle := sMode1;
  6455.   OptionsDlg.Question := sMode2;
  6456.   OptionsDlg.OptionList.Add(sMode3);
  6457.   OptionsDlg.OptionList.Add(sMode4);
  6458.   OptionsDlg.OptionList.Add(sMode5);
  6459.   OptionsDlg.OptionList.Add(sMode6);
  6460.   
  6461.   Index := OptionsDlg.Execute - 1;
  6462.  
  6463.   OptionsDlg.Free;
  6464.  
  6465.   if (Index >= 0) then
  6466.   begin
  6467.     if (Index = Ord(dmHistory)) then
  6468.     begin
  6469.       DisplayHistoryStr := FloatToStr(FDisplayHistory);
  6470.       if (InputQuery(sHistoryRange, '', DisplayHistoryStr)) then
  6471.       FDisplayHistory := StrToFloat(DisplayHistoryStr);
  6472.     end;
  6473.     SetDisplayMode(TDisplayMode(Index));
  6474.   end;
  6475. end;
  6476.  
  6477. {------------------------------------------------------------------------------
  6478.     Procedure: TCustomPlot.CanPaste
  6479.   Description: Can we paste data from the Clipboard into TPlot ?
  6480.        Author: Mat Ballard
  6481.  Date created: 11/28/1999
  6482. Date modified: 11/28/2000 by Mat Ballard
  6483.       Purpose: check in with the clipboard, looking for text data
  6484.  Known Issues:
  6485.  ------------------------------------------------------------------------------}
  6486. function TCustomPlot.CanPaste: Boolean;
  6487. {$IFDEF LINUX}
  6488. var
  6489.   FormatList: TStringList;
  6490.   i: Integer;
  6491. {$ENDIF}
  6492. begin
  6493. {$IFDEF MSWINDOWS}
  6494.   CanPaste := (ClipBoard.HasFormat(CF_TEXT));
  6495. {$ENDIF}
  6496. {$IFDEF LINUX}
  6497.   CanPaste := FALSE;
  6498.   FormatList := TStringList.Create;
  6499.   Clipboard.SupportedFormats(FormatList);
  6500.   for i := 0 to FormatList.Count-1 do
  6501.   begin
  6502.     if (Pos('text/plain', FormatList.Strings[i]) > 0) then
  6503.     begin
  6504.       CanPaste := TRUE;
  6505.       exit;
  6506.     end;
  6507.   end;
  6508.   FormatList.Free;
  6509. {$ENDIF}
  6510. end;
  6511.  
  6512. {------------------------------------------------------------------------------
  6513.     Procedure: TCustomPlot.PasteSeriesClick
  6514.   Description: Pastes data from the Clipboard
  6515.        Author: Mat Ballard
  6516.  Date created: 12/1/1999
  6517. Date modified: 02/25/2000 by Mat Ballard
  6518.       Purpose: Collects the data from the Clipboard and runs the ParseData method on it.
  6519.  Known Issues: limited to 32 K under D1. Can be fixed with messy memory management.
  6520.  ------------------------------------------------------------------------------}
  6521. procedure TCustomPlot.PasteClick(
  6522.   Sender: TObject);
  6523. var
  6524.   TheData: TStringList;
  6525. {$IFDEF DELPHI1}
  6526.   LongStr: PChar;
  6527. {$ENDIF}
  6528. begin
  6529.   TheData := TStringList.Create;
  6530. {$IFDEF DELPHI1}
  6531.   GetMem(LongStr, 32767);
  6532.   Clipboard.GetTextBuf(LongStr, 32767);
  6533.   TheData.SetText(LongStr);
  6534.   FreeMem(LongStr, 32767);
  6535. {$ELSE}
  6536.   TheData.Text := Clipboard.AsText;
  6537. {$ENDIF}
  6538.   FSeriesList.ParseData(TheData, FHelpFile);
  6539.   TheData.Free;
  6540.  
  6541.   ZoomOutClick(Self);
  6542. end;
  6543.  
  6544. {------------------------------------------------------------------------------
  6545.     Procedure: TCustomPlot.LineBestFitClick
  6546.   Description: Initiates a Line of Best Fit.
  6547.        Author: Mat Ballard
  6548.  Date created: 12/1/1999
  6549. Date modified: 05/30/2001 by Mat Ballard
  6550.       Purpose: Sets the Instructions and the ScreenJob
  6551.  Known Issues:
  6552.  ------------------------------------------------------------------------------}
  6553. procedure TCustomPlot.LineBestFitClick(
  6554.   Sender: TObject);
  6555. var
  6556. {Variables used in least-squares fitting:}
  6557.   NoLeastSquarePts: Integer;
  6558.   SumX, SumY, SumXsq, SumXY, SumYsq: Double;
  6559.   Rsq: Single;
  6560. {  Slope, Intercept: Single; - are globals to allow drawing of line}
  6561.  
  6562.   procedure InitializeFit;
  6563.   begin
  6564. {Initialize the fit parameters:}
  6565.     NoLeastSquarePts := 0;
  6566.     SumX := 0;
  6567.     SumY := 0;
  6568.     SumXsq := 0;
  6569.     SumXY := 0;
  6570.     SumYsq := 0;
  6571.   end;
  6572.   
  6573. begin
  6574.   if (GetSeriesFromUser) then
  6575.   begin
  6576.     if ((FScreenJob = sjRightDrag) or
  6577.         (FScreenJob = sjLineOfBestFit)) then
  6578.     begin
  6579.       InitializeFit;
  6580.       pSeries.LineBestFit(XAxis.XofF(Selection.Left), XAxis.XofF(Selection.Right),
  6581.         NoLeastSquarePts,
  6582.         SumX, SumY, SumXsq, SumXY, SumYsq,
  6583.         Slope, Intercept, Rsq);
  6584.       SetResult(Slope, Intercept, Rsq);
  6585.       ZeroScreenStuff;
  6586.     end
  6587.     else if (FScreenJob = sjDualLineBestFit2) then
  6588.     begin
  6589.       InitializeFit;
  6590.       pSeries.LineBestFit(XAxis.XofF(Sel1.Left), XAxis.XofF(Sel1.Right),
  6591.         NoLeastSquarePts,
  6592.         SumX, SumY, SumXsq, SumXY, SumYsq,
  6593.         Slope, Intercept, Rsq);
  6594.       pSeries.LineBestFit(XAxis.XofF(Selection.Left), XAxis.XofF(Selection.Right),
  6595.         NoLeastSquarePts,
  6596.         SumX, SumY, SumXsq, SumXY, SumYsq,
  6597.         Slope, Intercept, Rsq);
  6598.       SetResult(Slope, Intercept, Rsq);
  6599.       ZeroScreenStuff;
  6600.     end
  6601.     else
  6602.     begin
  6603.       FInstructions.Clear;
  6604.       FInstructions.Add(sLBF);
  6605.       ScreenJob := sjLineOfBestFit;
  6606.       FResult.Visible := False;
  6607.       DoStyleChange(Self);
  6608.     end;
  6609.   end;
  6610. end;
  6611.  
  6612. {------------------------------------------------------------------------------
  6613.     Procedure: TCustomPlot.TwoRegionLineBestFitClick
  6614.   Description: Initiates a Two Region Line of Best Fit.
  6615.        Author: Mat Ballard
  6616.  Date created: 12/1/1999
  6617. Date modified: 05/30/2001 by Mat Ballard
  6618.       Purpose: Sets the FInstructions and the ScreenJob
  6619.  Known Issues:
  6620.  ------------------------------------------------------------------------------}
  6621. procedure TCustomPlot.TwoRegionLineBestFitClick(Sender: TObject);
  6622. begin
  6623.   if (GetSeriesFromUser) then
  6624.   begin
  6625.     if ((FScreenJob = sjRightDrag) or
  6626.         (FScreenJob = sjDualLineBestFit1)) then
  6627.     begin
  6628.       Selection.AssignToRect(Sel1);
  6629.       {Sel1.Left := Selection.Left;
  6630.       Sel1.Top := Selection.Top;
  6631.       Sel1.Right := Selection.Right;
  6632.       Sel1.Bottom := Selection.Bottom;}
  6633.       ScreenJob := sjDualLineBestFit2;
  6634.       FInstructions.Clear;
  6635.       FInstructions.Add(sDualInstruction + ' ' + sToFit);
  6636.       DoStyleChange(Self);
  6637.     end
  6638.     else
  6639.     begin
  6640.       FInstructions.Clear;
  6641.       FInstructions.Add(s2RLBF);
  6642.       ScreenJob := sjDualLineBestFit1;
  6643.       FResult.Visible := False;
  6644.       DoStyleChange(Self);
  6645.     end;
  6646.   end;
  6647. end;
  6648.  
  6649. {$IFDEF FUNCTIONS}
  6650. {------------------------------------------------------------------------------
  6651.     Procedure: TCustomPlot.FunctionClick
  6652.   Description: Creates a new series which is a function of existing series
  6653.        Author: Mat Ballard
  6654.  Date created: 04/03/2001
  6655. Date modified: 04/03/2001 by Mat Ballard
  6656.       Purpose: data manipulation
  6657.  Known Issues:
  6658.  ------------------------------------------------------------------------------}
  6659. procedure TCustomPlot.FunctionClick(Sender: TObject);
  6660. begin
  6661.   FSeriesList.FunctionSeries;
  6662.   ZoomOutClick(Self);
  6663. end;
  6664. {$ENDIF}
  6665.  
  6666. {------------------------------------------------------------------------------
  6667.     Procedure: TCustomPlot.SmoothSeriesClick
  6668.   Description: Smoothes the selected data Series
  6669.        Author: Mat Ballard
  6670.  Date created: 12/1/1999
  6671. Date modified: 02/25/2000 by Mat Ballard
  6672.       Purpose: Obtains the Smoothing Order then runs the selected Series' Smooth method
  6673.  Known Issues:
  6674.  ------------------------------------------------------------------------------}
  6675. procedure TCustomPlot.SmoothSeriesClick(
  6676.   Sender: TObject);
  6677. var
  6678.   SmoothOrder: Integer;
  6679.   SmoothStr: String;
  6680. begin
  6681.   if (GetSeriesFromUser) then
  6682.   begin
  6683.     SmoothStr := '10';
  6684.     if (InputQuery(sSmoothing1 + pSeries.Name,
  6685.                    sSmoothing2,
  6686.                    SmoothStr)) then
  6687.     begin
  6688.       try
  6689.         SmoothOrder := StrToInt(SmoothStr);
  6690.         pSeries.Smooth(SmoothOrder);
  6691.         DoStyleChange(Self);
  6692.       except
  6693.         ShowMessage(sSmoothFail);
  6694.       end;
  6695.     end;
  6696.   end;
  6697.   ZeroScreenStuff;
  6698. end;
  6699.  
  6700. {------------------------------------------------------------------------------
  6701.     Procedure: TCustomPlot.SortClick
  6702.   Description: sorts the selected data
  6703.        Author: Mat Ballard
  6704.  Date created: 04/25/2000
  6705. Date modified: 04/25/2000 by Mat Ballard
  6706.       Purpose: data management and manipulation
  6707.  Known Issues:
  6708.  ------------------------------------------------------------------------------}
  6709. procedure TCustomPlot.SortClick(Sender: TObject);
  6710. begin
  6711.   if (GetSeriesFromUser) then
  6712.   begin
  6713.     pSeries.Sort;
  6714.     DoStyleChange(Self);
  6715.   end;
  6716.   ZeroScreenStuff;
  6717. end;
  6718.  
  6719. procedure TCustomPlot.SplineClick(Sender: TObject);
  6720. begin
  6721.   if (GetSeriesFromUser) then
  6722.   begin
  6723.     Self.Spline(TheSeries);
  6724.     DoStyleChange(Self);
  6725.   end;
  6726.   ZeroScreenStuff;
  6727. end;
  6728.  
  6729. {------------------------------------------------------------------------------
  6730.      Function: TCustomPlot.Spline
  6731.   Description: wrapper for TSeriesList.Spline
  6732.        Author: Mat Ballard
  6733.  Date created: 12/1/1999
  6734. Date modified: 02/25/2000 by Mat Ballard
  6735.       Purpose: Adds a new, empty data Series to the graph
  6736.  Known Issues:
  6737.  ------------------------------------------------------------------------------}
  6738. function TCustomPlot.Spline(ASeries: Integer): Integer;
  6739. var
  6740.   Density: Word;
  6741.   pSplineSeries: TSeries;
  6742.   TheString: String;
  6743. begin
  6744.   Spline := -1;
  6745. {if it isn't already ...}
  6746.   pSeries := TSeries(FSeriesList.Items[ASeries]);
  6747.  
  6748.   TheString := '1';
  6749.   if (InputQuery(sSpline1, sSpline2, TheString)) then
  6750.   begin
  6751.     Density := StrToInt(TheString);
  6752.  
  6753.     ASeries := FSeriesList.Add(-1);
  6754.     pSplineSeries := TSeries(FSeriesList.Items[ASeries]);
  6755.     pSplineSeries.AllocateNoPts(pSeries.NoPts * (Density + 1));
  6756.  
  6757.     pSeries.DoSpline(Density, pSplineSeries);
  6758.  
  6759.     pSplineSeries.Name := sSpline3 + pSeries.Name;
  6760.     pSplineSeries.Pen.Style := psDot;
  6761.     pSplineSeries.Visible := TRUE;
  6762.     Spline := ASeries;
  6763. {should we call pSeries.ClearSpline ?}
  6764.     DoStyleChange(Self);
  6765.   end;
  6766. end;
  6767.  
  6768. {------------------------------------------------------------------------------
  6769.     Procedure: TCustomPlot.CompressSeriesClick
  6770.   Description: Reduces the number of data points of the selected Series by averaging the data
  6771.        Author: Mat Ballard
  6772.  Date created: 10/15/2000
  6773. Date modified: 10/15/2000 by Mat Ballard
  6774.       Purpose: data management and manipulation
  6775.  Known Issues:
  6776.  ------------------------------------------------------------------------------}
  6777. procedure TCustomPlot.CompressSeriesClick(
  6778.   Sender: TObject);
  6779. var
  6780.   CompressRatio: Integer;
  6781.   CompressStr: String;
  6782. begin
  6783.   if (GetSeriesFromUser) then
  6784.   begin
  6785.     if (pSeries.XDataRefCount > 0) then raise
  6786.       EComponentError.CreateFmt(
  6787.         sCompress1 + CRLF + sCompress2,
  6788.         [pSeries.Name, pSeries.XDataRefCount]);
  6789.  
  6790.     if (pSeries.ExternalXSeries) then raise
  6791.       EComponentError.CreateFmt(
  6792.         sCompress1 + CRLF + sCompress3,
  6793.         [pSeries.Name, pSeries.XDataSeries.Name]);
  6794.  
  6795.     CompressStr := '10';
  6796.     if (InputQuery(sCompress4 + pSeries.Name,
  6797.                    sCompress5,
  6798.                    CompressStr)) then
  6799.     begin
  6800.       try
  6801.         CompressRatio := StrToInt(CompressStr);
  6802.         pSeries.Compress(CompressRatio);
  6803.       except
  6804.         ShowMessage(sCompress6);
  6805.       end;
  6806.     end;
  6807.     DoStyleChange(Self);
  6808.   end;
  6809.   ZeroScreenStuff;
  6810. end;
  6811.  
  6812. {------------------------------------------------------------------------------
  6813.     Procedure: TCustomPlot.CompressAllSeriesClick
  6814.   Description: Reduces the number of data points in ALL Series by averaging the data
  6815.        Author: Mat Ballard
  6816.  Date created: 10/15/2000
  6817. Date modified: 10/15/2000 by Mat Ballard
  6818.       Purpose: data management and manipulation
  6819.  Known Issues:
  6820.  ------------------------------------------------------------------------------}
  6821. procedure TCustomPlot.CompressAllSeriesClick(
  6822.   Sender: TObject);
  6823. var
  6824.   CompressRatio: Integer;
  6825.   CompressStr: String;
  6826.   i: Integer;
  6827. begin
  6828.   CompressStr := '10';
  6829.   if (InputQuery(sCompressAll1,
  6830.                  sCompress5,
  6831.                  CompressStr)) then
  6832.   begin
  6833.     try
  6834.       CompressRatio := StrToInt(CompressStr);
  6835.       for i := 0 to FSeriesList.Count-1 do
  6836.         TSeries(FSeriesList.Items[i]).Compress(CompressRatio);
  6837.     except
  6838.       ShowMessage(sCompress6);
  6839.     end;
  6840.   end;
  6841.   DoStyleChange(Self);
  6842. end;
  6843.  
  6844. {------------------------------------------------------------------------------
  6845.     Procedure: TCustomPlot.ContractSeriesClick
  6846.   Description: Reduces the number of data points of the selected Series by throwing away the ends
  6847.        Author: Mat Ballard
  6848.  Date created: 12/1/1999
  6849. Date modified: 05/30/2001 by Mat Ballard
  6850.       Purpose: data management and manipulation
  6851.  Known Issues:
  6852.  ------------------------------------------------------------------------------}
  6853. procedure TCustomPlot.ContractSeriesClick(
  6854.   Sender: TObject);
  6855. var
  6856.   TheLeft,
  6857.   TheRight: Integer;
  6858. begin
  6859.   if (GetSeriesFromUser) then
  6860.   begin
  6861.     if (pSeries.XDataRefCount > 0) then raise
  6862.       EComponentError.CreateFmt(
  6863.         sContract1 + CRLF + sCompress2,
  6864.         [pSeries.Name, pSeries.XDataRefCount]);
  6865.  
  6866.     if (pSeries.ExternalXSeries) then raise
  6867.       EComponentError.CreateFmt(
  6868.         sContract1 + CRLF + sCompress3,
  6869.         [pSeries.Name, pSeries.XDataSeries.Name]);
  6870.  
  6871.     if ((FScreenJob = sjRightDrag) or
  6872.         (FScreenJob = sjContractSeries)) then
  6873.     begin
  6874.       TheLeft := pSeries.GetNearestPointToFX(Selection.Left);
  6875.       TheRight := pSeries.GetNearestPointToFX(Selection.Right);
  6876.       pSeries.Contract(TheLeft, TheRight);
  6877.       ZeroScreenStuff;
  6878.     end
  6879.     else
  6880.     begin
  6881.       FScreenJob := sjContractSeries;
  6882.       FInstructions.Clear;
  6883.       FInstructions.Add(sContract2);
  6884.       FInstructions.Add(sContract3);
  6885.       DoStyleChange(Self);
  6886.     end;
  6887.     DoStyleChange(Self);
  6888.   end;
  6889. end;
  6890.  
  6891. {------------------------------------------------------------------------------
  6892.     Procedure: TCustomPlot.ContractAllSeriesClick
  6893.   Description: Reduces the number of data points of the selected Series by throwing away the ends
  6894.        Author: Mat Ballard
  6895.  Date created: 12/1/1999
  6896. Date modified: 05/30/2001 by Mat Ballard
  6897.       Purpose: data management and manipulation
  6898.  Known Issues:
  6899.  ------------------------------------------------------------------------------}
  6900. procedure TCustomPlot.ContractAllSeriesClick(
  6901.   Sender: TObject);
  6902. var
  6903.   TheLeft,
  6904.   TheRight: Integer;
  6905.   i: Integer;
  6906. begin
  6907.   if ((FScreenJob = sjRightDrag) or
  6908.      (FScreenJob = sjContractAllSeries)) then
  6909.   begin
  6910.     TheLeft := TSeries(FSeriesList.Items[0]).GetNearestPointToFX(Selection.Left);
  6911.     TheRight := TSeries(FSeriesList.Items[0]).GetNearestPointToFX(Selection.Right);
  6912.     for i := 0 to FSeriesList.Count-1 do
  6913.       TSeries(FSeriesList.Items[i]).Contract(TheLeft, TheRight);
  6914.     ZeroScreenStuff;
  6915.   end
  6916.   else
  6917.   begin
  6918.     FScreenJob := sjContractAllSeries;
  6919.     FInstructions.Clear;
  6920.     FInstructions.Add(sContract2);
  6921.     FInstructions.Add(sContract3);
  6922.     DoStyleChange(Self);
  6923.   end;
  6924.   DoStyleChange(Self);
  6925. end;
  6926.  
  6927. {------------------------------------------------------------------------------
  6928.     Procedure: TCustomPlot.LegendClick
  6929.   Description: Sets the Legend Direction
  6930.        Author: Mat Ballard
  6931.  Date created: 12/1/1999
  6932. Date modified: 02/25/2000 by Mat Ballard
  6933.       Purpose:
  6934.  Known Issues:
  6935.  ------------------------------------------------------------------------------}
  6936. procedure TCustomPlot.LegendClick(
  6937.   Sender: TObject);
  6938. var
  6939.   Index: Integer;
  6940.   OptionsDlg: TOptionsDlg;
  6941. begin
  6942.   OptionsDlg := TOptionsDlg.Create(nil);
  6943.  
  6944.   OptionsDlg.FormTitle := sLegend;
  6945.   OptionsDlg.Question := sLegend2;
  6946.   OptionsDlg.OptionList.Add(sHorizontally);
  6947.   OptionsDlg.OptionList.Add(sVertically);
  6948.   
  6949.   Index := OptionsDlg.Execute - 1;
  6950.  
  6951.   OptionsDlg.Free;
  6952.  
  6953.   if (Index >= 0) then
  6954.   begin
  6955.     FLegend.Direction := TDirection(Index);
  6956.   end;
  6957.   ZeroScreenStuff;
  6958.   DoStyleChange(Self);
  6959. end;
  6960.  
  6961. {------------------------------------------------------------------------------
  6962.     Procedure: TCustomPlot.EditAxisClick
  6963.   Description: Runs the Axis Editor of the selected Axis
  6964.        Author: Mat Ballard
  6965.  Date created: 12/1/1999
  6966. Date modified: 06/28/2000 by Mat Ballard
  6967.       Purpose:
  6968.  Known Issues:
  6969.  ------------------------------------------------------------------------------}
  6970. procedure TCustomPlot.EditAxisClick(
  6971.   Sender: TObject);
  6972. var
  6973.   i: Integer;
  6974.   AxisEditor: TAxisEditorForm;
  6975.   AXP: TAxisProperty;
  6976. begin
  6977.   if (GetAxisFromUser(0)) then
  6978.   begin
  6979.     AxisEditor := TAxisEditorForm.Create(nil);
  6980.     AxisEditor.ThePlot := TObject(Self);
  6981.  
  6982.     if (FDisplayMode = dmHistory) then
  6983.       AxisEditor.HistoryMode := TRUE;
  6984.  
  6985. {Iterate over all axes:}
  6986.     for i := 0 to FAxisList.Count-1 do
  6987.     begin
  6988.       pAxis := TAxis(FAxisList.Items[i]);
  6989.       AXP.LabelFormat := pAxis.Labels.NumberFormat;
  6990.       AXP.LabelDigits := pAxis.Labels.Digits;
  6991.       AXP.LabelPrecision := pAxis.Labels.Precision;
  6992.       AXP.LabelDirection := pAxis.Labels.Direction;
  6993.       AXP.PenColor := pAxis.Pen.Color;
  6994.       AXP.PenWidthIndex := pAxis.Pen.Width;
  6995.       AXP.PenStyleIndex := Ord(pAxis.Pen.Style);
  6996.       AXP.TickSize := pAxis.TickSize;
  6997.       AXP.TickDirection := pAxis.TickDirection;
  6998.       AXP.TickStepSize := pAxis.StepSize;
  6999.       AXP.TickMinors := pAxis.TickMinor;
  7000.       AXP.ScaleMin := pAxis.Min;
  7001.       AXP.ScaleMax := pAxis.Max;
  7002.       AXP.ScaleIntercept := pAxis.Intercept;
  7003.       AXP.ScaleAuto := pAxis.AutoScale;
  7004.       AXP.ScaleLog := pAxis.LogScale;
  7005.       AXP.ArrowSize := pAxis.ArrowSize;
  7006.       AXP.ArrowDirection := pAxis.Alignment;
  7007.       AXP.Visible := pAxis.Visible;
  7008.       AXP.LimitLower := pAxis.LimitLower;
  7009.       AXP.LimitUpper := pAxis.LimitUpper;
  7010.       AXP.LimitsVisible := pAxis.LimitsVisible;
  7011.       if (TObject(FAxisList.Items[i]) is TAngleAxis) then
  7012.       begin
  7013.         AXP.ZAngle := TAngleAxis(pAxis).Angle;
  7014.         AXP.ZLength := TAngleAxis(pAxis).Length;
  7015.         AXP.ZInterceptY := TAngleAxis(pAxis).ZInterceptY;
  7016.       end
  7017.       else
  7018.       begin
  7019.         AXP.ZAngle := 0;
  7020.         AXP.ZLength := 0;
  7021.       end;
  7022.       AxisEditor.AddAxis(pAxis.Title.Caption, AXP);
  7023.     end;
  7024.  
  7025.     if (TheAxis >= 0) then
  7026.       AxisEditor.NoComboBox.ItemIndex := TheAxis;
  7027.     AxisEditor.SelectAxis(TheAxis);
  7028.     AxisEditor.HelpFile := FHelpFile;
  7029.  
  7030.     if (AxisEditor.ShowModal = mrOK) then
  7031.       ApplyAxisChange(AxisEditor);
  7032.  
  7033.     AxisEditor.Free;
  7034.  
  7035.     ZeroScreenStuff;
  7036.   end; {GetAxisFrom User}
  7037. end;
  7038.  
  7039. {------------------------------------------------------------------------------
  7040.     Procedure: TCustomPlot.ApplyAxisChange
  7041.   Description: This applies changes from the PropertiesDialog.
  7042.        Author: Mat Ballard
  7043.  Date created: 03/28/2001
  7044. Date modified: 03/28/2001 by Mat Ballard
  7045.       Purpose: User interface management
  7046.  Known Issues:
  7047.  ------------------------------------------------------------------------------}
  7048. procedure TCustomPlot.ApplyAxisChange(Sender: TObject);
  7049. var
  7050.   i: Integer;
  7051.   pAXP: ^TAxisProperty;
  7052. begin
  7053.   for i := 0 to FAxisList.Count-1 do
  7054.   begin
  7055.     pAXP := TAxisEditorForm(Sender).AxisPropertyList.Items[i];
  7056.     pAxis := TAxis(FAxisList.Items[i]);
  7057.     pAxis.Title.Caption := TAxisEditorForm(Sender).AxisNames.Strings[i];
  7058.     pAxis.Labels.NumberFormat := pAXP^.LabelFormat;
  7059.     pAxis.Labels.Digits := pAXP^.LabelDigits;
  7060.     pAxis.Labels.Precision := pAXP^.LabelPrecision;
  7061.     pAxis.Labels.Direction := pAXP^.LabelDirection;
  7062.     pAxis.Pen.Color := pAXP^.PenColor;
  7063.     pAxis.Pen.Width := pAXP^.PenWidthIndex;
  7064.     pAxis.Pen.Style := TPenStyle(pAXP^.PenStyleIndex);
  7065.     pAxis.TickSize := pAXP^.TickSize;
  7066.     pAxis.TickDirection := pAXP^.TickDirection;
  7067.     pAxis.TickMinor := pAXP^.TickMinors;
  7068.     pAxis.AutoScale := pAXP^.ScaleAuto;
  7069.     pAxis.StepSize := pAXP^.TickStepSize;
  7070.     pAxis.Min := pAXP^.ScaleMin;
  7071.     pAxis.Max := pAXP^.ScaleMax;
  7072.     pAxis.Intercept := pAXP^.ScaleIntercept;
  7073.     pAxis.LogScale := pAXP^.ScaleLog;
  7074.     pAxis.ArrowSize := pAXP^.ArrowSize;
  7075.     pAxis.Alignment := pAXP^.ArrowDirection;
  7076.     pAxis.LimitLower := pAXP^.LimitLower;
  7077.     pAxis.LimitUpper := pAXP^.LimitUpper;
  7078.     pAxis.LimitsVisible := pAXP^.LimitsVisible;
  7079.     if (TObject(FAxisList.Items[i]) is TAngleAxis) then
  7080.     begin
  7081.       TAngleAxis(pAxis).Angle := pAXP^.ZAngle;
  7082.       TAngleAxis(pAxis).Length := pAXP^.ZLength;
  7083.       TAngleAxis(pAxis).ZInterceptY := pAXP^.ZInterceptY;
  7084.     end;
  7085.     pAxis.Visible := pAXP^.Visible;
  7086.     pAxis.ReScale;
  7087.   end; {for}
  7088.   {DoStyleChange(Self);}
  7089. end;
  7090.  
  7091. {------------------------------------------------------------------------------
  7092.     Procedure: TCustomPlot.NewNoteClick
  7093.   Description: Creates a new note
  7094.        Author: Mat Ballard
  7095.  Date created: 11/1/2000
  7096. Date modified: 11/1/2000 by Mat Ballard
  7097.       Purpose: appearance management
  7098.  Known Issues:
  7099.  ------------------------------------------------------------------------------}
  7100. procedure TCustomPlot.NewNoteClick(Sender: TObject);
  7101. var
  7102.   ANote: TNote;
  7103. begin
  7104.   ANote := TNote.Create(Self);
  7105.   ANote.MoveTo(Selection.Left, Selection.Top);
  7106.   ANote.ArrowLeft := Selection.Left + 1;
  7107.   ANote.ArrowTop := Selection.Top + 1;
  7108.   ANote.Tag := Ord(soNote);
  7109.  
  7110.   ScreenObjectList.Add(ANote);
  7111.   Inc(NoteCount);
  7112.   //NoteList.Add(ANote);
  7113.   pClickedObject := ANote;
  7114.   Screen.Cursor := crScope;
  7115.   ScreenJob := sjMoveNotePointer;
  7116.   FInstructions.Clear;
  7117.   FInstructions.Add(sNewNoteClick1);
  7118.   DoStyleChange(Self);
  7119. end;
  7120.  
  7121. {------------------------------------------------------------------------------
  7122.     Procedure: TCustomPlot.DeleteNoteClick
  7123.   Description: Moves a note pointer
  7124.        Author: Mat Ballard
  7125.  Date created: 11/22/2000
  7126. Date modified: 11/22/2000 by Mat Ballard
  7127.       Purpose: appearance management
  7128.  Known Issues:
  7129.  ------------------------------------------------------------------------------}
  7130. procedure TCustomPlot.MoveNotePointerClick(Sender: TObject);
  7131. begin
  7132.   if (GetNoteFromUser) then
  7133.     FScreenJob := sjMoveNotePointer;
  7134. end;
  7135.  
  7136. {------------------------------------------------------------------------------
  7137.     Procedure: TCustomPlot.DeleteNoteClick
  7138.   Description: Deletes a note
  7139.        Author: Mat Ballard
  7140.  Date created: 11/14/2000
  7141. Date modified: 11/14/2000 by Mat Ballard
  7142.       Purpose: appearance management
  7143.  Known Issues:
  7144.  ------------------------------------------------------------------------------}
  7145. procedure TCustomPlot.DeleteNoteClick(Sender: TObject);
  7146. begin
  7147.   if (GetNoteFromUser) then
  7148.   begin
  7149.     ScreenObjectList.Remove(pClickedObject);
  7150.     Dec(NoteCount);
  7151.     TNote(pClickedObject).Free;
  7152.     DoStyleChange(Self);
  7153.   end;
  7154.   ZeroScreenStuff;
  7155. end;
  7156.  
  7157. {------------------------------------------------------------------------------
  7158.     Procedure: TCustomPlot.EditFontClick
  7159.   Description: Edits the font of the selected Axis
  7160.        Author: Mat Ballard
  7161.  Date created: 12/1/1999
  7162. Date modified: 02/25/2000 by Mat Ballard
  7163.       Purpose: Runs the Font common Dialog box, and applies the results to the selected object
  7164.  Known Issues:
  7165.  ------------------------------------------------------------------------------}
  7166. procedure TCustomPlot.EditFontClick(
  7167.   Sender: TObject);
  7168. var
  7169.   TheFont: TFont;
  7170.   FontDialog: TFontDialog;
  7171.   OptionsDlg: TOptionsDlg;
  7172.   TheResult: Integer;
  7173. begin
  7174. {has the user already selected an object ?}
  7175.   if ((ClickedObjectType = soNone) or
  7176.       (ClickedObjectType = soXAxis) or
  7177.       (ClickedObjectType = soYAxis) or
  7178.       (ClickedObjectType = soLeftBorder) or
  7179.       (ClickedObjectType = soTopBorder) or
  7180.       (ClickedObjectType = soRightBorder) or
  7181.       (ClickedObjectType = soBottomBorder)) then
  7182.   begin
  7183. {get the user to select an object:}
  7184.     OptionsDlg := TOptionsDlg.Create(nil);
  7185.  
  7186.     OptionsDlg.FormTitle := sEditFont1;
  7187.     OptionsDlg.Question := sEditFont2;
  7188.     OptionsDlg.OptionList.Add(sEditFont3);
  7189.     OptionsDlg.OptionList.Add(sEditFont4);
  7190.     OptionsDlg.OptionList.Add(sEditFont5);
  7191.     OptionsDlg.OptionList.Add(sEditFont6);
  7192.     OptionsDlg.OptionList.Add(sEditFont7);
  7193.     OptionsDlg.OptionList.Add(sEditFont8);
  7194.     OptionsDlg.OptionList.Add(sEditFont9);
  7195.     OptionsDlg.OptionList.Add(sEditFont10);
  7196.     OptionsDlg.OptionList.Add(sEditFont11);
  7197.  
  7198.     TheResult := OptionsDlg.Execute;
  7199.     case TheResult of
  7200.       1: ClickedObjectType := soTitle;
  7201.       2: ClickedObjectType := soXAxisTitle;
  7202.       3: ClickedObjectType := soYAxisTitle;
  7203.       5: ClickedObjectType := soXAxisLabel;
  7204.       6: ClickedObjectType := soYAxisLabel;
  7205.       8: ClickedObjectType := soLegend;
  7206.       9: ClickedObjectType := soResult;
  7207.     end;
  7208.  
  7209.     OptionsDlg.Free;
  7210.   end; {if object selected}
  7211.  
  7212.   FontDialog := TFontDialog.Create(Self);
  7213.  
  7214.   case ClickedObjectType of
  7215.     soTitle: TheFont := FTitle.Font;
  7216.     soXAxisTitle: TheFont := FXAxis.Title.Font;
  7217.     soYAxisTitle: TheFont := TTitle(pClickedObject).Font;
  7218.     soXAxisLabel: TheFont := FXAxis.Labels.Font;
  7219.     soYAxisLabel: TheFont := TAxisLabel(pClickedObject).Font;
  7220.     soLegend: TheFont := FLegend.Font;
  7221.     soResult: TheFont := FResult.Font;
  7222.     soNote: TheFont := TNote(pClickedObject).Font;
  7223.   else
  7224. {assign TheFont:}
  7225.     //TheFont := nil;
  7226.     FontDialog.Free;
  7227. {don't like bugging out here, but is most elegant solution:}
  7228.     exit;
  7229.   end;
  7230.   FontDialog.Font.Assign(TheFont);
  7231.  
  7232.   if (FontDialog.Execute) then
  7233.   begin
  7234.     TheFont.Assign(FontDialog.Font);
  7235.     DoStyleChange(Self);
  7236.   end;
  7237.  
  7238.   ZeroScreenStuff;
  7239.   FontDialog.Free;
  7240. end;
  7241.  
  7242. {------------------------------------------------------------------------------
  7243.     Procedure: TCustomPlot.EditPropertiesClick
  7244.   Description: Edits the other properties of the Plot
  7245.        Author: Mat Ballard
  7246.  Date created: 10/10/2000
  7247. Date modified: 10/10/2000 by Mat Ballard
  7248.       Purpose: Runs the Properties Dialog box, and applies the results to the selected objects
  7249.  Known Issues:
  7250.  ------------------------------------------------------------------------------}
  7251. procedure TCustomPlot.EditPropertiesClick(
  7252.   Sender: TObject);
  7253. var
  7254.   PlotPropertyEditor: TPlotPropertyEditorForm;
  7255. begin
  7256.   PlotPropertyEditor := TPlotPropertyEditorForm.Create(nil);
  7257.   PlotPropertyEditor.ThePlot := TObject(Self);
  7258.   PlotPropertyEditor.HelpFile := FHelpFile;
  7259.  
  7260.   PlotPropertyEditor.PlotTypeComboBox.ItemIndex := Ord(FPlotType);
  7261.   PlotPropertyEditor.BackColorEdit.Color := Self.Color;
  7262.   PlotPropertyEditor.BackColorEdit.Text := ColorToString(Self.Color);
  7263.   PlotPropertyEditor.BubbleSizeNEdit.AsInteger := FBubbleSize;
  7264.   PlotPropertyEditor.ClickAndDragDelayNEdit.AsInteger := MouseTimer.Interval;
  7265.   PlotPropertyEditor.ColumnGapNEdit.AsInteger := FColumnGap;
  7266.   PlotPropertyEditor.ContourDetailComboBox.ItemIndex := Ord(FContourDetail);
  7267.   PlotPropertyEditor.ContourIntervalNEdit.AsReal := FContourInterval;
  7268.   PlotPropertyEditor.ContourStartNEdit.AsReal := FContourStart;
  7269.   PlotPropertyEditor.ContourWireFrameCheckBox.Checked := FContourWireFrame;
  7270.   PlotPropertyEditor.GridComboBox.ItemIndex := Ord(FGrid);
  7271.   PlotPropertyEditor.GridStyleComboBox.ItemIndex := Ord(FGridStyle);
  7272.   PlotPropertyEditor.GridColorEdit.Color := FGridColor;
  7273.   PlotPropertyEditor.GridColorEdit.Text := ColorToString(FGridColor);
  7274.   PlotPropertyEditor.LinkZSeriesCheckBox.Checked := FZLink;
  7275.   PlotPropertyEditor.MultiplicityComboBox.ItemIndex := FMultiplicity - 1;
  7276.   PlotPropertyEditor.MultiJoinEdit.Text := GetMultiJoin;
  7277.   PlotPropertyEditor.PenColorEdit.SetColour(FMultiplePen.Color);
  7278.   PlotPropertyEditor.PenWidthComboBox.ItemIndex := FMultiplePen.Width;
  7279.   PlotPropertyEditor.PenStyleComboBox.ItemIndex := Ord(FMultiplePen.Style);
  7280.   PlotPropertyEditor.PolarRangeNEdit.AsReal := FPolarRange;
  7281.   PlotPropertyEditor.PieRowCountComboBox.ItemIndex := FPieRowCount - 1;
  7282.   PlotPropertyEditor.PrintOrientationComboBox.ItemIndex := Ord(FPrintOrientation);
  7283.   PlotPropertyEditor.WallColorEdit.Color := FWallColor;
  7284.   PlotPropertyEditor.WallColorEdit.Text := ColorToString(FWallColor);
  7285.   PlotPropertyEditor.XYFastAtNEdit.AsInteger := FXYFastAt;
  7286.   PlotPropertyEditor.ZAxisAngleNEdit.AsInteger := ZAngle;
  7287.   PlotPropertyEditor.ZLengthNEdit.AsInteger := ZLength;
  7288. {$IFDEF DELPHI1}
  7289.   PlotPropertyEditor.CreatedByEdit.Visible := FALSE;
  7290.   PlotPropertyEditor.DescriptionEdit.Visible := FALSE;
  7291. {$ELSE}
  7292.   PlotPropertyEditor.CreatedByEdit.Text := FCreatedBy;
  7293.   PlotPropertyEditor.DescriptionEdit.Text := FDescription;
  7294. {$ENDIF}
  7295.  
  7296.   if (PlotPropertyEditor.ShowModal = mrOK) then
  7297.     ApplyPropertiesChange(PlotPropertyEditor);
  7298.  
  7299.   PlotPropertyEditor.Free;
  7300.  
  7301.   ZeroScreenStuff;
  7302. end;
  7303.  
  7304. {------------------------------------------------------------------------------
  7305.     Procedure: TCustomPlot.ApplyPropertiesChange
  7306.   Description: This applies changes from the PropertiesDialog.
  7307.        Author: Mat Ballard
  7308.  Date created: 03/28/2001
  7309. Date modified: 03/28/2001 by Mat Ballard
  7310.       Purpose: User interface management
  7311.  Known Issues:
  7312.  ------------------------------------------------------------------------------}
  7313. procedure TCustomPlot.ApplyPropertiesChange(Sender: TObject);
  7314. var
  7315.   OldIgnoreChanges: Boolean;
  7316. begin
  7317.   with TPlotPropertyEditorForm(Sender) do
  7318.   begin
  7319.     OldIgnoreChanges := IgnoreChanges;
  7320.     IgnoreChanges := TRUE;
  7321.     MouseTimer.Interval := ClickAndDragDelayNEdit.AsInteger;
  7322.     Self.Color := BackColorEdit.Color;
  7323.     FBubbleSize := BubbleSizeNEdit.AsInteger;
  7324.     FColumnGap := ColumnGapNEdit.AsInteger;
  7325.     FContourDetail := TContourDetail(ContourDetailComboBox.ItemIndex);
  7326.     FContourInterval := ContourIntervalNEdit.AsReal;
  7327.     FContourStart := ContourStartNEdit.AsReal;
  7328.     FContourWireFrame := ContourWireFrameCheckBox.Checked;
  7329.     FGrid := TGridType(GridComboBox.ItemIndex);
  7330.     FGridStyle := TPenStyle(GridStyleComboBox.ItemIndex);
  7331.     FGridColor := GridColorEdit.Color;
  7332.     FMultiplePen.Width := PenWidthComboBox.ItemIndex;
  7333.     FMultiplePen.Style := TPenStyle(PenStyleComboBox.ItemIndex);
  7334.     FMultiplicity := MultiplicityComboBox.ItemIndex + 1;
  7335.     FMultiplePen.Color := PenColorEdit.Color;
  7336.     SetMultiJoin(MultiJoinEdit.Text);
  7337.     FPieRowCount := PieRowCountComboBox.ItemIndex + 1;
  7338.     FPolarRange := PolarRangeNEdit.AsReal;
  7339.     FPrintOrientation := TPrinterOrientation(PrintOrientationComboBox.ItemIndex);
  7340.     FWallColor := WallColorEdit.Color;
  7341.     FXYFastAt := XYFastAtNEdit.AsInteger;
  7342.     ZAngle := ZAxisAngleNEdit.AsInteger;
  7343.     ZLength := ZLengthNEdit.AsInteger;
  7344.     FZLink := LinkZSeriesCheckBox.Checked;
  7345. {$IFNDEF DELPHI1}
  7346.     FCreatedBy := CreatedByEdit.Text;
  7347.     FDescription := DescriptionEdit.Text;
  7348. {$ENDIF}
  7349.     PlotType := TPlotType(PlotTypeComboBox.ItemIndex);
  7350.     IgnoreChanges := OldIgnoreChanges;
  7351.     DoStyleChange(Self);
  7352. {Required for 3D walls to display properly:}
  7353.     if (FGrid > gtNone) then
  7354.       if (FPlotType >= pt3DContour) then
  7355.       begin
  7356.         Application.ProcessMessages;
  7357.         Refresh;
  7358.       end;
  7359.   end;
  7360. end;
  7361.  
  7362. {------------------------------------------------------------------------------
  7363.     Procedure: TCustomPlot.EditPointClick
  7364.   Description: Runs the Point Editor of the selected data point
  7365.        Author: Mat Ballard
  7366.  Date created: 12/1/1999
  7367. Date modified: 02/25/2000 by Mat Ballard
  7368.       Purpose:
  7369.  Known Issues:
  7370.  ------------------------------------------------------------------------------}
  7371. procedure TCustomPlot.EditPointClick(
  7372.   Sender: TObject);
  7373. begin
  7374.   if (GetSeriesFromUser) then
  7375.   begin
  7376.     pSeries.EditPoint(ThePointNumber, FHelpFile);
  7377.     //DoStyleChange(Self);
  7378.   end;
  7379.   ZeroScreenStuff;
  7380. end;
  7381.  
  7382. {------------------------------------------------------------------------------
  7383.     Procedure: TCustomPlot.GetNoteFromUser
  7384.   Description: Gets the user to select (if not already done so) a Axis
  7385.        Author: Mat Ballard
  7386.  Date created: 12/1/1999
  7387. Date modified: 02/25/2000 by Mat Ballard
  7388.       Purpose: user interface management
  7389.  Known Issues:
  7390.  ------------------------------------------------------------------------------}
  7391. function TCustomPlot.GetNoteFromUser: Boolean;
  7392. var
  7393.   OptionsDlg: TOptionsDlg;
  7394.   i: Integer;
  7395.   TheNote: Integer;
  7396. begin
  7397. {has the user already selected an object ?}
  7398.   if (ClickedObjectType <> soNote) then
  7399.   begin
  7400.     if (NoteCount = 1) then
  7401.     begin
  7402. {there is only one Note:}
  7403.       ClickedObjectType := soNote;
  7404.       for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  7405.       begin
  7406.         if (TObject(ScreenObjectList.Items[i]) is TNote) then
  7407.         begin
  7408.           pClickedObject := ScreenObjectList.Items[i];
  7409.           break;
  7410.         end;
  7411.       end;
  7412.     end;
  7413.  
  7414.     if (ClickedObjectType <> soNote) then
  7415.   {still no Note selected:}
  7416.     begin
  7417.   {get the user to select an object:}
  7418.       OptionsDlg := TOptionsDlg.Create(nil);
  7419.       OptionsDlg.FormTitle := sWhichNote;
  7420.       OptionsDlg.Question := sWhichNoteDel;
  7421.       for i := NoBasicScreenObjects to ScreenObjectList.Count-1 do
  7422.       begin
  7423.         if (TObject(ScreenObjectList.Items[i]) is TNote) then
  7424.           OptionsDlg.OptionList.AddObject(
  7425.             TNote(ScreenObjectList.Items[i]).Caption,
  7426.             TNote(ScreenObjectList.Items[i]));
  7427.       end;
  7428.       TheNote := OptionsDlg.Execute - 1;
  7429.       if (TheNote >= 0) then
  7430.       begin
  7431.         ClickedObjectType := soNote;
  7432.         pClickedObject :=
  7433.           OptionsDlg.OptionList.Objects[TheNote];
  7434.           //ScreenObjectList.Items[NoBasicScreenObjects + TheNote];
  7435.       end;
  7436.       OptionsDlg.Free;
  7437.     end; {if object selected}
  7438.   end; {if clicked object is Series}
  7439.   GetNoteFromUser := (ClickedObjectType = soNote);
  7440. end;
  7441.  
  7442. {------------------------------------------------------------------------------
  7443.     Procedure: TCustomPlot.GetSeriesFromUser
  7444.   Description: Gets the user to select (if not already done so) a Axis
  7445.        Author: Mat Ballard
  7446.  Date created: 12/1/1999
  7447. Date modified: 02/25/2000 by Mat Ballard
  7448.       Purpose: user interface management
  7449.  Known Issues:
  7450.  ------------------------------------------------------------------------------}
  7451. function TCustomPlot.GetSeriesFromUser: Boolean;
  7452. var
  7453.   OptionsDlg: TOptionsDlg;
  7454.   i: Integer;
  7455. begin
  7456. {has the user already selected an object ?}
  7457.   if (ClickedObjectType <> soSeries) then
  7458.   begin
  7459.     ThePointNumber := 0;
  7460.     if (FSeriesList.Count = 1) then
  7461.     begin
  7462. {there is only one Series:}
  7463.       ClickedObjectType := soSeries;
  7464.       TheSeries := 0;
  7465.       pSeries := TSeries(FSeriesList.Items[0]);
  7466.     end;
  7467.  
  7468.     if (ClickedObjectType <> soSeries) then
  7469.   {still no Series selected:}
  7470.     begin
  7471.   {get the user to select an object:}
  7472.       OptionsDlg := TOptionsDlg.Create(nil);
  7473.       OptionsDlg.FormTitle := sWhichSeries;
  7474.       OptionsDlg.Question := sWhichSeries2;
  7475.       for i := 0 to FSeriesList.Count-1 do
  7476.       begin
  7477.         OptionsDlg.OptionList.Add(TSeries(FSeriesList.Items[i]).Name);
  7478.       end;
  7479.       TheSeries := OptionsDlg.Execute - 1;
  7480.       if (TheSeries >= 0) then
  7481.       begin
  7482.         ClickedObjectType := soSeries;
  7483.         pSeries := TSeries(FSeriesList.Items[TheSeries]);
  7484.       end;
  7485.       OptionsDlg.Free;
  7486.     end; {if object selected}
  7487.   end; {if clicked object is Series}
  7488.   GetSeriesFromUser := (TheSeries >= 0);
  7489. end;
  7490.  
  7491. {------------------------------------------------------------------------------
  7492.     Procedure: TCustomPlot.GetAxisFromUser
  7493.   Description: Gets the user to select (if not already done so) a Axis
  7494.        Author: Mat Ballard
  7495.  Date created: 06/25/1999
  7496. Date modified: 06/25/2000 by Mat Ballard
  7497.       Purpose: user interface management
  7498.  Known Issues:
  7499.  ------------------------------------------------------------------------------}
  7500. function TCustomPlot.GetAxisFromUser(StartAxis: Word): Boolean;
  7501. var
  7502.   OptionsDlg: TOptionsDlg;
  7503.   i,
  7504.   TheResult: Integer;
  7505. begin
  7506. {has the user already selected an object ?}
  7507. {see GetTheClickedObject}
  7508.   if ((TheAxis >= StartAxis) and (pAxis <> nil)) then
  7509.   begin
  7510.     GetAxisFromUser := TRUE;
  7511.     exit;
  7512.   end;
  7513.  
  7514.   if (StartAxis = FAxisList.Count - 1) then
  7515.   begin
  7516. {there is only one Axis that it could be:}
  7517.     ClickedObjectType := soYAxis;
  7518. {NB: the Y Axes are numbered 1, 2..N:}
  7519.     TheAxis := StartAxis;
  7520.     pAxis := TAxis(FAxisList.Items[TheAxis]);
  7521.     GetAxisFromUser := TRUE;
  7522.     exit;
  7523.   end;
  7524.  
  7525. {still no Axis selected:}
  7526. {get the user to select an object:}
  7527.   OptionsDlg := TOptionsDlg.Create(nil);
  7528.   OptionsDlg.FormTitle := sWhichAxis;
  7529.   OptionsDlg.Question := sWhichAxis2;
  7530.   for i := StartAxis to FAxisList.Count-1 do
  7531.   begin
  7532.     OptionsDlg.OptionList.Add(TAxis(FAxisList.Items[i]).Name);
  7533.   end;
  7534.  
  7535.   TheResult := OptionsDlg.Execute;
  7536.   if (TheResult > 0) then
  7537.   begin
  7538.     TheAxis := StartAxis + TheResult - 1; {Execute = -1, 1,2,3}
  7539.     if (TheAxis = 0) then
  7540.       ClickedObjectType := soXAxis;
  7541.     if (TheAxis > 0) then
  7542.       ClickedObjectType := soYAxis;
  7543.     pAxis := TAxis(FAxisList.Items[TheAxis]);
  7544.   end;
  7545.   OptionsDlg.Free;
  7546.  
  7547.   if (TheAxis >= 0) then
  7548.     GetAxisFromUser := TRUE
  7549.    else
  7550.     GetAxisFromUser := FALSE;
  7551. end;
  7552.  
  7553. {------------------------------------------------------------------------------
  7554.     Procedure: TCustomPlot.EditDataClick
  7555.   Description: Runs the Data Editor for the selected Series
  7556.        Author: Mat Ballard
  7557.  Date created: 03/13/2001
  7558. Date modified: 03/13/2001 by Mat Ballard
  7559.       Purpose:
  7560.  Known Issues:
  7561.  ------------------------------------------------------------------------------}
  7562. procedure TCustomPlot.EditDataClick(
  7563.   Sender: TObject);
  7564. begin
  7565.   if (GetSeriesFromUser) then
  7566.   begin
  7567.     pSeries.EditData(FHelpFile);
  7568.   end; {GetSeries}
  7569.   ZeroScreenStuff;
  7570.   Refresh;
  7571. end;
  7572.  
  7573. {------------------------------------------------------------------------------
  7574.     Procedure: TCustomPlot.EditSeriesClick
  7575.   Description: Runs the Series Editor of the selected data Series
  7576.        Author: Mat Ballard
  7577.  Date created: 12/1/1999
  7578. Date modified: 02/25/2000 by Mat Ballard
  7579.       Purpose:
  7580.  Known Issues:
  7581.  ------------------------------------------------------------------------------}
  7582. procedure TCustomPlot.EditSeriesClick(
  7583.   Sender: TObject);
  7584. var
  7585.   i: Integer;
  7586.   SeriesEditor: TSeriesEditorForm;
  7587.   ASP: TSeriesProperty;
  7588.   pSeries: TSeries;
  7589. begin
  7590.   if (GetSeriesFromUser) then
  7591.   begin
  7592.     SeriesEditor := TSeriesEditorForm.Create(nil);
  7593.     SeriesEditor.ThePlot := TObject(Self);
  7594.  
  7595. {Load the Y Axis Combo Box:}
  7596.     for i := 1 to FAxisList.Count-1 do
  7597.     begin
  7598.       SeriesEditor.YAxisComboBox.Items.Add(TAxis(FAxisList.Items[i]).Title.Caption);
  7599.     end;
  7600.  
  7601. {Iterate over all series:}
  7602.     for i := 0 to FSeriesList.Count-1 do
  7603.     begin
  7604.       pSeries := TSeries(FSeriesList.Items[i]);
  7605. {returns 0..MY_COLORS_MAX}
  7606.       ASP.PenColor := pSeries.Pen.Color;
  7607.       ASP.PenWidthIndex := pSeries.Pen.Width;
  7608.       ASP.PenStyleIndex := Ord(pSeries.Pen.Style);
  7609.       ASP.BrushColor := pSeries.Brush.Color;
  7610.       ASP.BrushStyleIndex := Ord(pSeries.Brush.Style);
  7611.       ASP.SymbolIndex := Ord(pSeries.Symbol);
  7612.       ASP.SymbolSize := pSeries.SymbolSize;
  7613.       ASP.YAxisIndex := pSeries.YAxisIndex;
  7614.       ASP.DeltaX := pSeries.DeltaX;
  7615.       ASP.DeltaY := pSeries.DeltaY;
  7616.       ASP.XDataIndependent := not pSeries.ExternalXSeries;
  7617.       ASP.ExternalXSeries := pSeries.ExternalXSeries;
  7618.       ASP.Visible := pSeries.Visible;
  7619.       ASP.ShadeLimits := pSeries.ShadeLimits;
  7620.       SeriesEditor.AddSeries(pSeries.Name, ASP);
  7621.     end;
  7622.     SeriesEditor.NoComboBox.ItemIndex := TheSeries;
  7623.     SeriesEditor.SelectSeries(TheSeries);
  7624.  
  7625.     SeriesEditor.HelpFile := FHelpFile;
  7626.  
  7627.     if (SeriesEditor.ShowModal = mrOK) then
  7628.       ApplySeriesChange(SeriesEditor);
  7629.  
  7630.     SeriesEditor.Free;
  7631.   end;
  7632.   ZeroScreenStuff;
  7633. end;
  7634.  
  7635. {------------------------------------------------------------------------------
  7636.     Procedure: TCustomPlot.ApplySeriesChange
  7637.   Description: This applies changes from the SeriesEditor Dialog.
  7638.        Author: Mat Ballard
  7639.  Date created: 03/28/2001
  7640. Date modified: 03/28/2001 by Mat Ballard
  7641.       Purpose: User interface management
  7642.  Known Issues:
  7643.  ------------------------------------------------------------------------------}
  7644. procedure TCustomPlot.ApplySeriesChange(Sender: TObject);
  7645. var
  7646.   i: Integer;
  7647.   pSeries: TSeries;
  7648.   pASP: ^TSeriesProperty;
  7649. begin
  7650.   for i := 0 to FSeriesList.Count-1 do
  7651.   begin
  7652.     pASP := TSeriesEditorForm(Sender).SeriesPropertyList.Items[i];
  7653.     pSeries := TSeries(FSeriesList.Items[i]);
  7654.     pSeries.Pen.Color := pASP^.PenColor;
  7655.     pSeries.Pen.Width := pASP^.PenWidthIndex;
  7656.     pSeries.Pen.Style := TPenStyle(pASP^.PenStyleIndex);
  7657.     pSeries.Brush.Color := pASP^.BrushColor;
  7658.     pSeries.Brush.Style := TBrushStyle(pASP.BrushStyleIndex);
  7659.     pSeries.Symbol := TSymbol(pASP^.SymbolIndex);
  7660.     pSeries.SymbolSize := pASP^.SymbolSize;
  7661.     pSeries.YAxisIndex := pASP^.YAxisIndex;
  7662.     pSeries.DeltaX := pASP^.DeltaX;
  7663.     pSeries.DeltaY := pASP^.DeltaY;
  7664.     pSeries.Visible := pASP^.Visible;
  7665.     pSeries.Name := TSeriesEditorForm(Sender).SeriesNames.Strings[i];
  7666.     pSeries.ShadeLimits := pASP^.ShadeLimits;
  7667.     if ((pASP^.XDataIndependent) and (pSeries.ExternalXSeries)) then
  7668.     begin
  7669. {this series did depend on X Data in another series,
  7670. but user wants to make it independent:}
  7671.       pSeries.MakeXDataIndependent;
  7672.     end;
  7673.   end; {for}
  7674.   DoStyleChange(Self);
  7675. end;
  7676.  
  7677. {------------------------------------------------------------------------------
  7678.     Procedure: TCustomPlot.ResetDisplacementClick
  7679.   Description: Puts the selected Axis back where it came from
  7680.        Author: Mat Ballard
  7681.  Date created: 12/1/1999
  7682. Date modified: 02/25/2000 by Mat Ballard
  7683.       Purpose: sets the DeltaX and DeltaY properties of the selected Axis to ZeroScreenStuff
  7684.  Known Issues:
  7685.  ------------------------------------------------------------------------------}
  7686. procedure TCustomPlot.ResetDisplacementClick(
  7687.   Sender: TObject);
  7688. begin
  7689.   if (GetSeriesFromUser) then
  7690.   begin
  7691.     pSeries.DeltaX := 0;
  7692.     pSeries.DeltaY := 0;
  7693.     DoStyleChange(Self);
  7694.   end;
  7695.   ZeroScreenStuff;
  7696. end;
  7697.  
  7698. {File manipulation ------------------------------------------------------------}
  7699. {------------------------------------------------------------------------------
  7700.     Procedure: TCustomPlot.NewClick
  7701.   Description: Creates a new, blank Graph
  7702.        Author: Mat Ballard
  7703.  Date created: 02/25/2000
  7704. Date modified: 02/25/2000 by Mat Ballard
  7705.       Purpose: data management
  7706.  Known Issues:
  7707.  ------------------------------------------------------------------------------}
  7708. procedure TCustomPlot.NewClick(
  7709.   Sender: TObject);
  7710. begin
  7711.   Self.Clear(TRUE);
  7712. end;
  7713.  
  7714. {------------------------------------------------------------------------------
  7715.     Procedure: TPlot.Notification
  7716.   Description: needed for D1
  7717.        Author: Mat Ballard
  7718.  Date created: 09/07/2000
  7719. Date modified: 09/07/2000 by Mat Ballard
  7720.       Purpose:
  7721.  Known Issues:
  7722.  ------------------------------------------------------------------------------}
  7723. procedure TCustomPlot.Notification(AComponent: TComponent;
  7724.   Operation: TOperation);
  7725. begin
  7726.   inherited Notification(AComponent, Operation);
  7727.   {if (Operation = opRemove) and (AComponent = Plot) then
  7728.   begin
  7729.     Plot := nil;
  7730.   end;}
  7731. end;
  7732.  
  7733. {------------------------------------------------------------------------------
  7734.     Procedure: TCustomPlot.OpenClick
  7735.   Description: Opens a file on disk
  7736.        Author: Mat Ballard
  7737.  Date created: 02/25/2000
  7738. Date modified: 02/25/2000 by Mat Ballard
  7739.       Purpose: Runs the File Open common dialog then the LoadFromFile method
  7740.  Known Issues:
  7741.  ------------------------------------------------------------------------------}
  7742. procedure TCustomPlot.OpenClick(
  7743.   Sender: TObject);
  7744. var
  7745.   OpenDialog: TOpenDialog;
  7746. begin
  7747. {We have to display a File Open Dialog:}
  7748.   OpenDialog := TOpenDialog.Create(Self);
  7749.   OpenDialog.Title := sOpen;
  7750.   OpenDialog.Filter := FileTypes;
  7751.   OpenDialog.Options := [ofOverwritePrompt];
  7752.   if (Length(FFileName) = 0) then
  7753.   begin
  7754.     FileName := '*.' + FDefaultExtension;
  7755.   end;
  7756.  
  7757.   OpenFilterIndex := GetFilterIndex(GetFileExtension);
  7758.   OpenDialog.FilterIndex := OpenFilterIndex;
  7759.  
  7760.   OpenDialog.FileName := '*.' + GetFileExtension;
  7761.  
  7762.   if (Length(OpenDriveDir) > 0) then
  7763.     OpenDialog.InitialDir := ExtractFileName(OpenDriveDir)
  7764.    else
  7765.     OpenDialog.InitialDir := GetFileDriveDir;
  7766.  
  7767.   if (OpenDialog.Execute) then
  7768.   begin
  7769.     OpenFile(OpenDialog.FileName);
  7770.     OpenFilterIndex := OpenDialog.FilterIndex;
  7771.   end;
  7772.   OpenDialog.Free;
  7773.  
  7774.   //ZoomOutClick(Self);
  7775. end;
  7776.  
  7777. {------------------------------------------------------------------------------
  7778.     Procedure: TCustomPlot.OpenFile
  7779.   Description: Opens a file on disk
  7780.        Author: Mat Ballard
  7781.  Date created: 08/12/2000
  7782. Date modified: 08/12/2000 by Mat Ballard
  7783.       Purpose: Called from TPlotMenu.HandleFileClick
  7784.  Known Issues:
  7785.  ------------------------------------------------------------------------------}
  7786. procedure TCustomPlot.OpenFile(
  7787.   TheFile: String);
  7788. begin
  7789.   if (FileExists(TheFile)) then
  7790.   begin
  7791. {Delete any existing Series:}
  7792.     Clear(FALSE);
  7793.     FileName := TheFile;
  7794.     OpenDriveDir := ExtractFilePath(FFileName);
  7795. {Finally, Open it:}
  7796.     LoadFromFile(FFileName);
  7797.  
  7798.     DoFileOpen(FFileName);
  7799.   end;
  7800.  
  7801.   ZoomOutClick(Self);
  7802. end;
  7803.  
  7804. {------------------------------------------------------------------------------
  7805.     Procedure: TCustomPlot.DoFileOpen
  7806.   Description: Fires the OnFileOpen event
  7807.        Author: Mat Ballard
  7808.  Date created: 09/07/2000
  7809. Date modified: 09/07/2000 by Mat Ballard
  7810.       Purpose:
  7811.  Known Issues:
  7812.  ------------------------------------------------------------------------------}
  7813. procedure TCustomPlot.DoFileOpen(AFileName: String);
  7814. begin
  7815.   if Assigned(FOnFileOpen) then
  7816.     OnFileOpen(Self, AFileName);
  7817. end;
  7818.  
  7819.  
  7820. {------------------------------------------------------------------------------
  7821.     Procedure: TCustomPlot.ClearOverlaysClick
  7822.   Description: Gets rid of the overlaid data
  7823.        Author: Mat Ballard
  7824.  Date created: 02/25/2000
  7825. Date modified: 02/25/2000 by Mat Ballard
  7826.       Purpose: Runs the FSeriesList.Delete method for each overlaid Axis
  7827.  Known Issues:
  7828.  ------------------------------------------------------------------------------}
  7829. procedure TCustomPlot.ClearOverlaysClick(
  7830.   Sender: TObject);
  7831. var
  7832.   i: Integer;
  7833. begin
  7834.   if (FirstOverlay < 0) then raise
  7835.     EComponentError.Create(sClearOverlaysClick1);
  7836.  
  7837.   for i := FSeriesList.Count-1 downto FirstOverlay do
  7838.   begin
  7839.     TSeries(FSeriesList.Items[i]).Free;
  7840.     FSeriesList.Delete(i);
  7841.   end;
  7842.   FirstOverlay := -1;
  7843.   DoStyleChange(Self);
  7844. end;
  7845.  
  7846. {------------------------------------------------------------------------------
  7847.     Procedure: TCustomPlot.OverlayDataClick
  7848.   Description: Overlays data
  7849.        Author: Mat Ballard
  7850.  Date created: 02/25/2000
  7851. Date modified: 02/25/2000 by Mat Ballard
  7852.       Purpose: Runs the Open common dialog, then LoadFromFile the selected files
  7853.  Known Issues:
  7854.  ------------------------------------------------------------------------------}
  7855. procedure TCustomPlot.OverlayClick(
  7856.   Sender: TObject);
  7857. var
  7858.   i: Integer;
  7859.   OverlayDialog: TOpenDialog;
  7860. begin
  7861. {We have to display a File Overlay Dialog:}
  7862.   OverlayDialog := TOpenDialog.Create(Self);
  7863.   OverlayDialog.Title := sOverlay1;
  7864.   OverlayDialog.Filter := FileTypes;
  7865.   OverlayDialog.Options :=
  7866.     [ofFileMustExist, ofPathMustExist, ofAllowMultiSelect];
  7867.  
  7868.   OverlayDialog.FileName := '*.' + FDefaultExtension;
  7869.  
  7870.   OverlayDialog.FilterIndex := OpenFilterIndex;
  7871.  
  7872.   if (Length(OverlayDriveDir) > 0) then
  7873.     OverlayDialog.InitialDir := ExtractFileName(OpenDriveDir)
  7874.    else
  7875.     OverlayDialog.InitialDir := GetFileDriveDir;
  7876.  
  7877.   if (OverlayDialog.Execute) then
  7878.   begin
  7879.     FirstOverlay := FSeriesList.Count;
  7880.     for i := 0 to OverlayDialog.Files.Count - 1 do
  7881.     begin
  7882.       OverlayDriveDir := ExtractFileName(OverlayDialog.Files.Strings[i]);
  7883. {Finally, Overlay it:}
  7884.       Self.LoadFromFile(OverlayDialog.Files.Strings[i]);
  7885.     end;
  7886.   end;
  7887.   OverlayDialog.Free;
  7888.  
  7889.   ZoomOutClick(Self);
  7890. end;
  7891.  
  7892. {------------------------------------------------------------------------------
  7893.     Procedure: TCustomPlot.SaveImageClick
  7894.   Description: saves the current plot as an image
  7895.        Author: Mat Ballard
  7896.  Date created: 04/25/2000
  7897. Date modified: 04/25/2000 by Mat Ballard
  7898.       Purpose: responds to "Save Image" menu selection
  7899.  Known Issues:
  7900.  ------------------------------------------------------------------------------}
  7901. procedure TCustomPlot.SaveImageClick(Sender: TObject);
  7902. var
  7903.   SaveImageDialog: TSaveDialog;
  7904.   Extension, ImageName: String;
  7905. begin
  7906. {We have to display a File Save Dialog:}
  7907.   SaveImageDialog := TSaveDialog.Create(Self);
  7908.   SaveImageDialog.Title := sSaveImage1;
  7909.   SaveImageDialog.Filter := PICTURE_TYPES;
  7910.   SaveImageDialog.Options := [ofOverwritePrompt];
  7911.  
  7912.   if (Length(ImageDriveDir) = 0) then
  7913.     if (Length(FFileName) > 0) then
  7914.       ImageDriveDir := GetFileDriveDir;
  7915.  
  7916.   SaveImageDialog.FilterIndex := ImageFilterIndex;
  7917. {which starts off at zero, then  may change}
  7918.  
  7919.   if (Length(FFileName) > 0) then
  7920.   begin
  7921.     SaveImageDialog.FileName :=
  7922.       GetFileRoot + '.' + ImageExtensions[ImageFilterIndex-1];
  7923.   end
  7924.   else
  7925.   begin
  7926.     SaveImageDialog.FileName :=
  7927.       '*.' + ImageExtensions[ImageFilterIndex-1];
  7928.   end;
  7929.  
  7930.   SaveImageDialog.InitialDir := ImageDriveDir;
  7931.  
  7932.   if (SaveImageDialog.Execute) then
  7933.   begin
  7934.     ImageName := SaveImageDialog.FileName;
  7935.     ImageDriveDir := ExtractFilePath(ImageName);
  7936.  
  7937.     Extension := LowerCase(ExtractFileExt(ImageName));
  7938.     if (Length(Extension) = 0) then
  7939.     begin
  7940.       Extension := '.' +
  7941.         ImageExtensions[SaveImageDialog.FilterIndex-1];
  7942.       ImageName := ImageName + Extension;
  7943.     end;
  7944.  
  7945. {Finally, save it:}
  7946. {We base this on the extension, rather than FilterIndex:}
  7947.     if (Extension = '.bmp') then
  7948.     begin
  7949.       ImageFilterIndex := 3;
  7950.       SaveAsBitMap(ImageName);
  7951.     end;
  7952. {.$ IFDEF MSWINDOWS}
  7953.     if (Extension = '.wmf') then
  7954.     begin
  7955.       ImageFilterIndex := 1;
  7956.       SaveAsDrawing(ImageName);
  7957.     end
  7958.     else if (Extension = '.emf') then
  7959.     begin
  7960.       ImageFilterIndex := 2;
  7961.       SaveAsDrawing(ImageName);
  7962.     end;
  7963. {.$ ENDIF}
  7964. {$IFDEF GIF}
  7965.     if (Extension = '.gif') then
  7966.     begin
  7967.       ImageFilterIndex := 4;
  7968.       SaveAsGIF(ImageName);
  7969.     end;
  7970. {$ENDIF}
  7971. {$IFDEF PNG}
  7972.     if (Extension = '.png') then
  7973.     begin
  7974.       ImageFilterIndex := 5;
  7975.       SaveAsPNG(ImageName);
  7976.     end;
  7977. {$ENDIF}
  7978.   end;
  7979.   SaveImageDialog.Free;
  7980. end;
  7981.  
  7982. {------------------------------------------------------------------------------
  7983.     Procedure: TCustomPlot.SaveClick
  7984.   Description: Saves the graph
  7985.        Author: Mat Ballard
  7986.  Date created: 02/25/2000
  7987. Date modified: 02/25/2000 by Mat Ballard
  7988.       Purpose: Runs SaveToFile or SaveAsClick
  7989.  Known Issues:
  7990.  ------------------------------------------------------------------------------}
  7991. procedure TCustomPlot.SaveClick(Sender: TObject);
  7992. begin
  7993.   if (Length(FFileName) > 0) then
  7994.     SaveToFile(FFileName)
  7995.    else
  7996.     SaveAsClick(Sender);
  7997. end;
  7998.  
  7999. {------------------------------------------------------------------------------
  8000.     Procedure: TCustomPlot.SaveAsClick
  8001.   Description: Saves the data to disk
  8002.        Author: Mat Ballard
  8003.  Date created: 02/25/2000
  8004. Date modified: 02/25/2000 by Mat Ballard
  8005.       Purpose: Runs the Save common dialog box then SaveToFile
  8006.  Known Issues:
  8007.  ------------------------------------------------------------------------------}
  8008. procedure TCustomPlot.SaveAsClick(Sender: TObject);
  8009. var
  8010.   Ext: String;
  8011.   SaveDialog: TSaveDialog;
  8012. begin
  8013. {We have to display a File Save Dialog:}
  8014.   SaveDialog := TSaveDialog.Create(Self);
  8015.   SaveDialog.Title := sSaveAs1;
  8016.   SaveDialog.Filter := FileTypes;
  8017.   SaveDialog.Options := [ofOverwritePrompt];
  8018.   if (Length(FFileName) = 0) then
  8019.   begin
  8020.     FileName := '*.' + FDefaultExtension;
  8021.   end;
  8022.  
  8023.   SaveFilterIndex := GetFilterIndex(GetFileExtension);
  8024.   SaveDialog.FilterIndex := SaveFilterIndex;
  8025.  
  8026.   SaveDialog.InitialDir := GetFileDriveDir;
  8027.   SaveDialog.FileName := ExtractFileName(FFileName);
  8028.  
  8029.   if (SaveDialog.Execute) then
  8030.   begin
  8031.     FileName := SaveDialog.FileName;
  8032.     Ext := GetFileExtension;
  8033.     if (Length(Ext) = 0) then
  8034.     begin
  8035.       Ext := FileExtensions[SaveDialog.FilterIndex];
  8036.       FileName := FileName + '.' + Ext;
  8037.     end;
  8038.  
  8039. {Double-whammy problem: save with 'plot'extension, but different filter,
  8040.  should save in that (text) format.
  8041.  Save with other extension, but FilterIndex=0 (plot type), then extension
  8042.  should override, so also save in text.}
  8043.  
  8044.     if ((Ext = FileExtensions[0]) and (SaveDialog.FilterIndex = 1)) then
  8045.     begin {.plot}
  8046.       SaveFilterIndex := 1;
  8047.       FAsText := FALSE or (soAsText in FSaveOptions);
  8048.     end {.plot}
  8049.     else if ((Ext = FileExtensions[0]) and (SaveDialog.FilterIndex > 1)) then
  8050.     begin {'plot' extension, text type}
  8051.       SaveFilterIndex := 1;
  8052.       FAsText := TRUE;
  8053.     end {'plot' extension, text type}
  8054.     else if (Ext = FileExtensions[1]) then
  8055.     begin {.csv}
  8056.       SaveFilterIndex := 2;
  8057.       FAsText := TRUE;
  8058.     end {.csv}
  8059.     else if (Ext = FileExtensions[2]) then
  8060.     begin
  8061.       SaveFilterIndex := 3;
  8062.       FAsText := TRUE;
  8063.     end {.txt}
  8064.     else
  8065.     begin
  8066.       SaveFilterIndex := 4;
  8067.       FAsText := TRUE;
  8068.     end; {.*}
  8069.  
  8070. {Finally, save it:}
  8071.     Self.SaveToFile(FFileName);
  8072.     SaveFilterIndex := SaveDialog.FilterIndex;
  8073.   end;
  8074.   SaveDialog.Free;
  8075. end;
  8076.  
  8077. {Saving data to disk --------------------------------------------------------}
  8078. {------------------------------------------------------------------------------
  8079.     Procedure: TCustomPlot.LoadFromFile
  8080.   Description: Opens data on disk
  8081.        Author: Mat Ballard
  8082.  Date created: 02/25/2000
  8083. Date modified: 02/25/2000 by Mat Ballard
  8084.       Purpose: Opens the data and feeds it into LoadFromStream
  8085.  Known Issues: Can be called by either OpenClick or OverlayClick
  8086.  ------------------------------------------------------------------------------}
  8087. procedure TCustomPlot.LoadFromFile(
  8088.   AFileName: String);
  8089. var
  8090.  TheStream: TMemoryStream;
  8091. begin
  8092.  TheStream := TMemoryStream.Create;
  8093.  try
  8094.    TheStream.LoadFromFile(AFileName);
  8095.    Self.LoadFromStream(TheStream);
  8096.  finally
  8097.    TheStream.Free;
  8098.  end;
  8099. end;
  8100.  
  8101. {------------------------------------------------------------------------------
  8102.     Procedure: TCustomPlot.LoadFromStream
  8103.   Description: Opens data on disk
  8104.        Author: Mat Ballard
  8105.  Date created: 02/25/2000
  8106. Date modified: 02/25/2000 by Mat Ballard
  8107.       Purpose: Opens data, parses it, fires the OnHeader event, and runs ConvertTextData,
  8108.                or decides to run it through ParseData instead
  8109.  Known Issues: Can be called by either OpenClick or OverlayClick
  8110.  ------------------------------------------------------------------------------}
  8111. procedure TCustomPlot.LoadFromStream(
  8112.   AStream: TMemoryStream);
  8113. var
  8114.   TheResult: Boolean;
  8115.   TheStrings: TStringList;
  8116.   OldIgnoreChanges: Boolean;
  8117.  
  8118.   function IsPlotFile: Boolean;
  8119.   var
  8120.     FileVersion: Integer;
  8121.     TheLine: String;
  8122.   begin
  8123.     IsPlotFile := FALSE;
  8124. {Line the first:}
  8125.     TheLine := ReadLine(AStream);
  8126.     if (Pos('TPlot', TheLine) = 0) then exit;
  8127.  
  8128. {Line the second:}
  8129.     TheLine := ReadLine(AStream);
  8130.     if (Pos('FileFormat', TheLine) = 0) then exit;
  8131.     GetWord(TheLine, '=');
  8132.     FileVersion := StrToInt(TheLine);
  8133.     if (FileVersion > MAX_FILE_VERSION) then exit;
  8134.  
  8135.     FTitle.Caption := ReadLine(AStream);
  8136.  
  8137. {Now comes the developer-defined header:}
  8138.     DoHeader(AStream);
  8139.  
  8140.     TheLine := ReadLine(AStream);
  8141.     if (TheLine <> SUBHEADER) then
  8142.     begin
  8143. {either a stuffed file, or the developer has done a naughty
  8144.  and overrun his own header; we therefore try to find it from the beginning,
  8145.  then reset the srteam position:}
  8146.       AStream.Position := 0;
  8147.       if (not (FindStringInStream(SUBHEADER, AStream))) then exit;
  8148.       TheLine := ReadLine(AStream);
  8149.     end;
  8150.     IsPlotFile := TRUE;
  8151.   end;
  8152.  
  8153. begin
  8154.   OldIgnoreChanges := IgnoreChanges;
  8155.   IgnoreChanges := TRUE;
  8156.  
  8157.   if (IsPlotFile) then
  8158.   begin
  8159.     TheResult := FSeriesList.LoadFromStream(AStream, FAsText);
  8160.   end
  8161.   else
  8162.   begin
  8163. {maybe it's just a text file:}
  8164.     AStream.Seek(0, soFromBeginning);
  8165.     TheStrings := TStringList.Create;
  8166.     try
  8167.       TheStrings.LoadFromStream(AStream);
  8168.       TheResult := FSeriesList.ParseData(TheStrings, FHelpFile);
  8169.       {FAsText := TRUE;}
  8170.     finally
  8171.       if (TheStrings <> nil) then
  8172.         TheStrings.Free;
  8173.     end;
  8174.   end; {IsPlotFile}
  8175.  
  8176.   if (TheResult) then OpenProperties('');
  8177.  
  8178.   IgnoreChanges := OldIgnoreChanges;
  8179.   ZoomOutClick(Self);
  8180. end;
  8181.  
  8182. {------------------------------------------------------------------------------
  8183.     Procedure: TCustomPlot.DoHeader
  8184.   Description: Informs the user of a user-defined file header
  8185.        Author: Mat Ballard
  8186.  Date created: 09/07/2000
  8187. Date modified: 09/07/2000 by Mat Ballard
  8188.       Purpose: Fires the OnHeader event
  8189.  Known Issues:
  8190.  ------------------------------------------------------------------------------}
  8191. procedure TCustomPlot.DoHeader(TheStream: TMemoryStream);
  8192. begin
  8193.   if assigned(FOnHeader) then
  8194.     OnHeader(Self, TheStream);
  8195. end;
  8196.  
  8197. {------------------------------------------------------------------------------
  8198.     Procedure: TCustomPlot.SaveToFile
  8199.   Description: Saves the data as text
  8200.        Author: Mat Ballard
  8201.  Date created: 02/25/2000
  8202. Date modified: 03/07/2001 by Mat Ballard
  8203.       Purpose: Fires the OnHeaderRequest event, then the GetData of SeriesList
  8204.  Known Issues:
  8205.       Comment: Note that we now use a TStream.
  8206.  ------------------------------------------------------------------------------}
  8207. procedure TCustomPlot.SaveToFile(
  8208.   AFileName: String);
  8209. var
  8210.   TheStream: TMemoryStream;
  8211. begin
  8212.   TheStream := TMemoryStream.Create;
  8213. {create the data in binary or text format:}
  8214.   Self.SaveToStream(TheStream);
  8215.  
  8216. {determine the file name:}
  8217.   if (Length(AFileName) > 0) then
  8218.     SetFileName(AFileName);
  8219.  
  8220. {save it:}
  8221.   TheStream.SaveToFile(FFileName);
  8222.  
  8223.   TheStream.Free;
  8224.  
  8225.   if (soProperties in FSaveOptions) then
  8226.     SaveTheProperties('');
  8227. end;
  8228.  
  8229. {------------------------------------------------------------------------------
  8230.     Procedure: TCustomPlot.SaveToStream
  8231.   Description: Saves the data as text
  8232.        Author: Mat Ballard
  8233.  Date created: 02/25/2000
  8234. Date modified: 03/07/2001 by Mat Ballard
  8235.       Purpose: Fires the OnHeaderRequest event, then the GetData of SeriesList
  8236.  Known Issues:
  8237.       Comment: Note that we now use a TStream.
  8238.  ------------------------------------------------------------------------------}
  8239. procedure TCustomPlot.SaveToStream(var TheStream: TMemoryStream);
  8240. var
  8241.   pLine: array [0..1023] of char;
  8242. begin
  8243.   if (TheStream = nil) then
  8244.     TheStream := TMemoryStream.Create;
  8245.  
  8246. {D1 does not like Pointer(TheLine)^:
  8247.   TheLine := 'TPlot=' + IntToStr(TPLOT_VERSION) + CRLF;
  8248.   TheStream.Write(Pointer(TheLine)^, Length(TheLine));
  8249. so:}
  8250.   StrPCopy(pLine, 'TPlot=' + IntToStr(TPLOT_VERSION) + CRLF);
  8251.   TheStream.Write(pLine, StrLen(pLine));
  8252.   StrPCopy(pLine, 'FileFormat=' + IntToStr(FILE_FORMAT_VERSION) + CRLF);
  8253.   TheStream.Write(pLine, StrLen(pLine));
  8254.  
  8255.   StrPCopy(pLine, FTitle.Caption + CRLF);
  8256.   TheStream.Write(pLine, StrLen(pLine));
  8257.  
  8258.   DoHeaderRequest(TheStream);
  8259.  
  8260.   StrPCopy(pLine, SUBHEADER + CRLF);
  8261.   TheStream.Write(pLine, StrLen(pLine));
  8262.  
  8263. {create the data in binary or text format:}
  8264.   FSeriesList.GetStream(FAsText, ',', TheStream);
  8265. end;
  8266.  
  8267. {------------------------------------------------------------------------------
  8268.     Procedure: TCustomPlot.DoHeaderRequest
  8269.   Description: Asks the user for a header
  8270.        Author: Mat Ballard
  8271.  Date created: 09/07/2000
  8272. Date modified: 09/07/2000 by Mat Ballard
  8273.       Purpose: Fires the OnHeaderRequest event
  8274.  Known Issues:
  8275.  ------------------------------------------------------------------------------}
  8276. procedure TCustomPlot.DoHeaderRequest(TheStream: TMemoryStream);
  8277. begin
  8278.   if assigned(FOnHeaderRequest) then
  8279.     OnHeaderRequest(Self, TheStream);
  8280. end;
  8281.  
  8282. {------------------------------------------------------------------------------
  8283.     Procedure: TCustomPlot.OpenProperties
  8284.   Description: Opens the properties of this instance of TPlot
  8285.        Author: Mat Ballard
  8286.  Date created: 08/03/2000
  8287. Date modified: 08/03/2000 by Mat Ballard
  8288.       Purpose: Saves the appearance of the Plot
  8289.  Known Issues:
  8290.       Comment: Note that if AFileName is blank, we use a name generated from
  8291.                the FileName property (in SetFileName).
  8292.  ------------------------------------------------------------------------------}
  8293. procedure TCustomPlot.OpenProperties(AFileName: String);
  8294. var
  8295.   FileStream: TFileStream;
  8296.   OldIgnoreChanges: Boolean;
  8297. begin
  8298.   if (Length(AFileName) > 0) then
  8299.     PropsFileName := AFileName;
  8300.  
  8301.   if (FileExists(PropsFileName)) then
  8302.   begin
  8303.     OldIgnoreChanges := IgnoreChanges;
  8304.     IgnoreChanges := TRUE;
  8305.     FileStream := TFileStream.Create(PropsFileName, fmOpenRead + fmShareDenyWrite);
  8306.     try
  8307. {This is what causes multiple screen redraws. But why ?}
  8308.       FileStream.ReadComponent(Self);
  8309.       {The following dont work; TAxis descends from TPersistent !
  8310.       for i := 2 to FAxisList.Count-1 do
  8311.       begin
  8312.         TAxis(FAxisList[i]).ReadComponent(TAxis(FAxisList[i]));
  8313.       end;}
  8314.     finally
  8315.       IgnoreChanges := OldIgnoreChanges;
  8316.       FileStream.Free;
  8317.     end;
  8318.   end;
  8319. end;
  8320.  
  8321. {------------------------------------------------------------------------------
  8322.     Procedure: TCustomPlot.SaveTheProperties
  8323.   Description: Saves the properties of this instance of TPlot
  8324.        Author: Mat Ballard
  8325.  Date created: 08/03/2000
  8326. Date modified: 08/03/2000 by Mat Ballard
  8327.       Purpose: Saves the appearance of the Plot
  8328.  Known Issues:
  8329.       Comment: Note that if AFileName is blank, we use a name generated from
  8330.                the FileName property (in SetFileName).
  8331.  ------------------------------------------------------------------------------}
  8332. procedure TCustomPlot.SaveTheProperties(AFileName: String);
  8333. var
  8334.   FileStream: TFileStream;
  8335. begin
  8336.   if (Length(AFileName) > 0) then
  8337.     PropsFileName := AFileName;
  8338.  
  8339.   FileStream := TFileStream.Create(PropsFileName, fmCreate or fmShareExclusive);
  8340.   FileStream.WriteComponent(Self);
  8341.   {The following dont work; TAxis descends from TPersistent !
  8342.   for i := 2 to FAxisList.Count-1 do
  8343.   begin
  8344.     TAxis(FAxisList[i]).WriteComponent(TAxis(FAxisList[i]));
  8345.   end;}
  8346.   FileStream.Free;
  8347. end;
  8348.  
  8349. {------------------------------------------------------------------------------
  8350.     Procedure: TCustomPlot.AppendToFile
  8351.   Description: Appends the data to FileName
  8352.        Author: Mat Ballard
  8353.  Date created: 02/25/2000
  8354. Date modified: 02/25/2000 by Mat Ballard
  8355.       Purpose: Runs the GetData method of SeriesList, then the Append method of the new TFileList
  8356.  Known Issues: Needs work on GetData and testing
  8357.  ------------------------------------------------------------------------------}
  8358. procedure TCustomPlot.AppendToFile;
  8359. var
  8360.   TheStream: TMemoryStreamEx;
  8361. begin
  8362.   if (FileExists(FFileName)) then
  8363.   begin
  8364. {create the FileList, an extension of TStringList:}
  8365.     TheStream := TMemoryStreamEx.Create;
  8366.  
  8367. {create the data in text format:}
  8368.     FSeriesList.AppendStream((soAsText in FSaveOptions), ',', TheStream);
  8369. {save it:}
  8370.     TheStream.AppendToFile(FFileName);
  8371.  
  8372.     TheStream.Free;
  8373.   end
  8374.   else
  8375.   begin
  8376.     EComponentError.Create('TCustomPlot.AppendToFile: ' + FFileName + sDoesNoTExist);
  8377.   end;
  8378. end;
  8379.  
  8380. {Copying data to the clipboard ----------------------------------------------}
  8381. {------------------------------------------------------------------------------
  8382.     Procedure: TCustomPlot.CopyHTML
  8383.   Description: Copies data as HTML to Clipboard
  8384.        Author: Mat Ballard
  8385.  Date created: 02/25/2000
  8386. Date modified: 02/25/2000 by Mat Ballard
  8387.       Purpose: Creates a Header, fires the OnHTMLHeaderRequest event, then runs
  8388.                the DataAsHTMLTable method of SeriesList
  8389.  Known Issues:
  8390.  ------------------------------------------------------------------------------}
  8391. procedure TCustomPlot.CopyHTML(Format: Word);
  8392. var
  8393.   i: Integer;
  8394.   TheData,
  8395.   TheHeader: TStringList;
  8396. {$IFDEF DELPHI1}
  8397.   pLine: array [0..1023] of char;
  8398. {$ENDIF}
  8399. {$IFDEF MSWINDOWS}
  8400.   Size,
  8401.   LineLength: LongInt;
  8402.   pText,
  8403.   TextPtr: PChar;
  8404.   TextHandle: THandle;
  8405. {$ENDIF}
  8406. begin
  8407.   TheHeader := TStringList.Create;
  8408.   TheHeader.Add('<html>');
  8409.   TheHeader.Add('<head>');
  8410.   TheHeader.Add('<title>' + FTitle.Caption + '</title>');
  8411.   TheHeader.Add('</head>');
  8412.   TheHeader.Add('<body bgcolor="white">');
  8413.   TheHeader.Add('<h1>' + FTitle.Caption + '</h1>');
  8414.   TheHeader.Add('<p>');
  8415.  
  8416.   DoHTMLHeaderRequest(TheHeader);
  8417.  
  8418.   TheData := TStringList.Create;
  8419.  
  8420. {create the data in text format:}
  8421.   FSeriesList.DataAsHTMLTable(TheData);
  8422. {insert the header:}
  8423.   for i := 0 to TheHeader.Count-1 do
  8424.     TheData.Insert(0, TheHeader[i]);
  8425.  
  8426. {$IFDEF MSWINDOWS}
  8427. {Calculate the size:}
  8428.   Size := 8;
  8429.   for i := 0 to TheData.Count-1 do
  8430.     Inc(Size, Length(TheData[i])+2);
  8431. {save it:}
  8432.   TextHandle := GlobalAlloc(GMEM_MOVEABLE, Size);
  8433.   TextPtr := GlobalLock(TextHandle);
  8434.  
  8435.   pText := TextPtr;
  8436.   for i := 0 to TheData.Count - 1 do
  8437.   begin
  8438.     LineLength := Length(TheData[i]);
  8439.     if LineLength <> 0 then
  8440.     begin
  8441. {$IFDEF DELPHI1}
  8442.       StrPCopy(pLine, TheData[i]);
  8443.       System.Move(pLine, pText^, LineLength);
  8444. {$ELSE}
  8445. {for some unknown reason, this Move works !}
  8446.       System.Move(Pointer(TheData[i])^, pText^, LineLength);
  8447. {$ENDIF}
  8448.       Inc(pText, LineLength);
  8449.     end;
  8450.     pText^ := #13;
  8451.     Inc(pText);
  8452.     pText^ := #10;
  8453.     Inc(pText);
  8454.   end;       
  8455. {we need to use SetAsHandle because Format may be CF_HTML:}
  8456.   ClipBoard.SetAsHandle(Format, TextHandle);
  8457.   GlobalUnlock(TextHandle);
  8458. {$ENDIF}
  8459. {$IFDEF LINUX}
  8460.   Clipboard.AsText := TheData.Text;
  8461. {$ENDIF}
  8462.   TheHeader.Free;
  8463.   TheData.Free;
  8464. end;
  8465.  
  8466. {------------------------------------------------------------------------------
  8467.     Procedure: TCustomPlot.DoHTMLHeaderRequest
  8468.   Description: Asks the user for their HTML header data
  8469.        Author: Mat Ballard
  8470.  Date created: 09/07/2000
  8471. Date modified: 09/07/2000 by Mat Ballard
  8472.       Purpose: fires the OnHTMLHeaderRequest event
  8473.  Known Issues:
  8474.  ------------------------------------------------------------------------------}
  8475. procedure TCustomPlot.DoHTMLHeaderRequest(TheHeader: TStringList);
  8476. begin
  8477.   if assigned(FOnHTMLHeaderRequest) then
  8478.     OnHTMLHeaderRequest(Self, TheHeader);
  8479. end;
  8480.  
  8481. {------------------------------------------------------------------------------
  8482.     Procedure: TCustomPlot.CopyText
  8483.   Description: Copies data as tab-delimited text to Clipboard
  8484.        Author: Mat Ballard
  8485.  Date created: 02/25/2000
  8486. Date modified: 02/25/2000 by Mat Ballard
  8487.       Purpose: Creates a Header, fires the OnHeaderRequest event, then runs the GetData method of SeriesList
  8488.  Known Issues:
  8489.  ------------------------------------------------------------------------------}
  8490. procedure TCustomPlot.CopyText;
  8491. var
  8492.   TheStream: TMemoryStream;
  8493.   pLine: array [0..1023] of char;
  8494. {$IFDEF MSWINDOWS}
  8495.   TextPtr: Pointer;
  8496.   TextHandle: THandle;
  8497. {$ENDIF}
  8498. {$IFDEF LINUX}
  8499.   TheText: TStringList;
  8500. {$ENDIF}
  8501. begin
  8502.   StrPCopy(pLine, FTitle.Caption + CRLF);
  8503.   TheStream := TMemoryStream.Create;
  8504.   TheStream.Write(pLine, StrLen(pLine));
  8505.  
  8506.   DoHeaderRequest(TheStream);
  8507.  
  8508. {create the data in TEXT format:}
  8509.   FSeriesList.GetStream(TRUE, #9, TheStream);
  8510.  
  8511. {save it:}
  8512. {$IFDEF MSWINDOWS}
  8513.   TextHandle := GlobalAlloc(GMEM_MOVEABLE, TheStream.Size+1);
  8514.   TextPtr := GlobalLock(TextHandle);
  8515. {for some unknown reason, this Move works !}
  8516.   System.Move(TheStream.Memory^, TextPtr^, TheStream.Size);
  8517.   ClipBoard.SetAsHandle(CF_TEXT, TextHandle);
  8518.   GlobalUnlock(TextHandle);
  8519. {$ENDIF}
  8520. {$IFDEF LINUX}
  8521.   TheText := TStringList.Create;
  8522.   TheText.LoadFromStream(TheStream);
  8523.   ClipBoard.AsText := TheText.Text;
  8524.   TheText.Free;
  8525. {$ENDIF}
  8526.   TheStream.Free;
  8527. end;
  8528.  
  8529. {Copying picture to the clipboard -------------------------------------------}
  8530. {------------------------------------------------------------------------------
  8531.     Procedure: TCustomPlot.CopyBitmap
  8532.   Description: Copies a picture of the graph as a bitmap to the Clipboard
  8533.        Author: Mat Ballard
  8534.  Date created: 02/25/2000
  8535. Date modified: 02/25/2000 by Mat Ballard
  8536.       Purpose: Runs Draw method over Bitmap then copies Bitmap
  8537.  Known Issues:
  8538.  ------------------------------------------------------------------------------}
  8539. procedure TCustomPlot.CopyBitmap;
  8540. begin
  8541.   ClipBoard.Assign(Self.BitMap);
  8542. end;
  8543.  
  8544. {------------------------------------------------------------------------------
  8545.     Procedure: TCustomPlot.GetBitmap
  8546.   Description: Returns a picture of the graph as a bitmap
  8547.        Author: Mat Ballard
  8548.  Date created: 04/25/2001
  8549. Date modified: 04/25/2001 by Mat Ballard
  8550.       Purpose: Runs Draw method over Bitmap
  8551.  Known Issues:
  8552.  ------------------------------------------------------------------------------}
  8553. function TCustomPlot.GetBitmap: TBitmap;
  8554. var
  8555.   Rect: TRect;
  8556. begin
  8557.   Rect := GetClientRect;
  8558.   Result := TBitMap.Create;
  8559.   Result.Height := Rect.Bottom - Rect.Top;
  8560.   Result.Width := Rect.Right - Rect.Left;
  8561.  
  8562.   Draw(Result.Canvas);
  8563. end;
  8564.  
  8565. {------------------------------------------------------------------------------
  8566.     Procedure: TCustomPlot.SaveAsBitmap
  8567.   Description: Saves a picture of the graph as a bitmap
  8568.        Author: Mat Ballard
  8569.  Date created: 02/25/2000
  8570. Date modified: 02/25/2000 by Mat Ballard
  8571.       Purpose: Runs Draw method over Bitmap then saves Bitmap
  8572.  Known Issues:
  8573.  ------------------------------------------------------------------------------}
  8574. procedure TCustomPlot.SaveAsBitmap(
  8575.   AFileName: String);
  8576. begin
  8577.   Self.Bitmap.SaveToFile(AFileName);
  8578. end;
  8579.  
  8580. {------------------------------------------------------------------------------
  8581.      Function: TCustomPlot.GetDrawing
  8582.   Description: Returns a picture of the graph as a Windows Metafile to the Clipboard
  8583.        Author: Mat Ballard
  8584.  Date created: 05/16/2001
  8585. Date modified: 05/16/2001 by Mat Ballard
  8586.       Purpose: developer rendering image of TPlot
  8587.  Known Issues:
  8588.  ------------------------------------------------------------------------------}
  8589. {$IFDEF MSWINDOWS}
  8590. function TCustomPlot.GetDrawing: TMetafile;
  8591. var
  8592.   AMetafileCanvas: TMetafileCanvas;
  8593.   Rect: TRect;
  8594. begin
  8595.   Rect := GetClientRect;
  8596.   Result := TMetafile.Create;
  8597. {$IFDEF COMPILER3_UP}
  8598.   Result.Enhanced := TRUE;
  8599. {$ENDIF}
  8600.   Result.Height := Rect.Bottom - Rect.Top;
  8601.   Result.Width := Rect.Right - Rect.Left;
  8602.  
  8603. {$IFDEF DELPHI1}
  8604. {create the metafile canvas to draw on:}
  8605.   AMetafileCanvas :=
  8606.     TMetafileCanvas.Create(Result, 0);
  8607. {$ELSE}
  8608.   SetMetafileDescription;
  8609. {create the metafile canvas to draw on:}
  8610.   AMetafileCanvas :=
  8611.     TMetafileCanvas.CreateWithComment(Result, 0, FCreatedBy, FDescription);
  8612. {$ENDIF}
  8613.  
  8614. {draw the graph on the metafile:}
  8615.   Draw(AMetafileCanvas);
  8616.   AMetafileCanvas.Free;
  8617. end;
  8618. {$ENDIF}
  8619.  
  8620. {$IFDEF LINUX}
  8621. function TCustomPlot.GetDrawing: TDrawing;
  8622. var
  8623.   Rect: TRect;
  8624. begin
  8625.   Rect := GetClientRect;
  8626.   Result := TDrawing.Create;
  8627.   Result.Height := Rect.Bottom - Rect.Top;
  8628.   Result.Width := Rect.Right - Rect.Left;
  8629.  
  8630.   Result.Canvas.Start;
  8631.   try
  8632.     Draw(Result.Canvas);
  8633.   finally
  8634.     Result.Canvas.Stop;
  8635.   end;
  8636. end;
  8637. {$ENDIF}
  8638.  
  8639. {------------------------------------------------------------------------------
  8640.     Procedure: TCustomPlot.CopyDrawing
  8641.   Description: Copies a picture of the graph as a Windows Metafile to the Clipboard
  8642.        Author: Mat Ballard
  8643.  Date created: 02/25/2000
  8644. Date modified: 02/25/2000 by Mat Ballard
  8645.       Purpose: Runs Draw method over AMetafileCanvas then copies Metafile
  8646.  Known Issues:
  8647.  ------------------------------------------------------------------------------}
  8648. procedure TCustomPlot.CopyDrawing(Enhanced: Boolean);
  8649. {$IFDEF MSWINDOWS}
  8650. var
  8651.   AFormat: Word;
  8652.   AData: THandle;
  8653.   APalette: HPALETTE;
  8654. begin
  8655.   Self.Drawing.SaveToClipboardFormat(AFormat, AData, APalette);
  8656.   ClipBoard.SetAsHandle(AFormat, AData);
  8657. {$ENDIF}
  8658. {$IFDEF LINUX}
  8659. begin
  8660.   Clipboard.Assign(Self.Drawing);
  8661. {$ENDIF}
  8662. end;
  8663.  
  8664. {------------------------------------------------------------------------------
  8665.     Procedure: TCustomPlot.SaveAsDrawing
  8666.   Description: Saves a picture of the graph as a Windows Metafile
  8667.        Author: Mat Ballard
  8668.  Date created: 02/25/2000
  8669. Date modified: 02/25/2000 by Mat Ballard
  8670.       Purpose: Runs Draw method over Metafile Canvas then saves Metafile
  8671.  Known Issues:
  8672.  ------------------------------------------------------------------------------}
  8673. procedure TCustomPlot.SaveAsDrawing(
  8674.   AFileName: String);
  8675. begin
  8676.   Self.Drawing.SaveToFile(AFileName);
  8677. end;
  8678.  
  8679. {$IFDEF GIF}
  8680. {------------------------------------------------------------------------------
  8681.     Procedure: TCustomPlot.SaveAsGIF
  8682.   Description: Saves a picture of the graph as a GIF file
  8683.        Author: Mat Ballard
  8684.  Date created: 02/25/2000
  8685. Date modified: 02/25/2000 by Mat Ballard
  8686.       Purpose: Runs Draw method over ABitmap of AGifImage then saves AGifImage
  8687.  Known Issues: 1. Requires Anders Melander's TGifImage
  8688.                2. Package dependency problems means that it is easier to let end users add this functionality
  8689.  ------------------------------------------------------------------------------}
  8690. function TCustomPlot.GetGIF: TGIFImage;
  8691. var
  8692.   Rect: TRect;
  8693.   ABitMap: TBitMap;
  8694. begin
  8695.   Rect := GetClientRect;
  8696.   ABitMap := TBitMap.Create;
  8697.   ABitMap.PixelFormat := pf24bit;
  8698.   ABitMap.Height := Rect.Bottom - Rect.Top;
  8699.   ABitMap.Width := Rect.Right - Rect.Left;
  8700.   Self.Draw(ABitMap.Canvas);
  8701.  
  8702.   Result := TGIFImage.Create;
  8703.   Result.Assign(ABitMap);
  8704.   ABitMap.Free;
  8705. end;
  8706.  
  8707. procedure TCustomPlot.SaveAsGIF(
  8708.   AFileName: String);
  8709. begin
  8710.   Self.GIF.SaveToFile(AFileName);
  8711. end;
  8712. {$ENDIF}
  8713.  
  8714. {$IFDEF PNG}
  8715.   {$IFDEF MSWINDOWS}
  8716. function TCustomPlot.GetPNG: TPngimage;
  8717. var
  8718.   Rect: TRect;
  8719.   ABitmap: TBitmap;
  8720. begin
  8721.   Rect := GetClientRect;
  8722.   ABitmap := TBitmap.Create;
  8723. {We need 24 bit otherwise the 8 bit PNG renders white as black !}  
  8724.   ABitmap.PixelFormat := pf24bit;
  8725.   ABitmap.Height := Rect.Bottom - Rect.Top;
  8726.   ABitmap.Width := Rect.Right - Rect.Left;
  8727.   Draw(ABitmap.Canvas);
  8728.  
  8729.   Result := TPngimage.Create;
  8730.   Result.Title := FTitle.Caption;
  8731.   Result.Author := FCreatedBy;
  8732.   Result.Description := FDescription;
  8733.   Result.Software := ExtractFileName(Application.ExeName);
  8734.   Result.CopyFromBmp(ABitmap);
  8735.   ABitmap.Free;
  8736. end;
  8737.   {$ENDIF}
  8738.   {$IFDEF LINUX}
  8739. function TCustomPlot.GetPNG: TBitmap;
  8740. var
  8741.   Rect: TRect;
  8742. begin
  8743.   Rect := GetClientRect;
  8744.   Result := TBitMap.Create;
  8745.   Result.Format := 'PNG';
  8746.   Result.Height := Rect.Bottom - Rect.Top;
  8747.   Result.Width := Rect.Right - Rect.Left;
  8748.  
  8749.   Draw(Result.Canvas);
  8750. end;
  8751.   {$ENDIF}
  8752. {------------------------------------------------------------------------------
  8753.     Procedure: TCustomPlot.SaveAsPNG
  8754.   Description: Saves a picture of the graph as a PNG file
  8755.        Author: Mat Ballard
  8756.  Date created: 02/25/2000
  8757. Date modified: 02/25/2000 by Mat Ballard
  8758.       Purpose: Runs Draw method over ABitmap of APngImage then saves APngImage
  8759.  Known Issues:
  8760.  ------------------------------------------------------------------------------}
  8761. procedure TCustomPlot.SaveAsPng(
  8762.   AFileName: String);
  8763. begin
  8764.   Self.Png.SaveToFile(AFileName);
  8765. end;
  8766. {$ENDIF}
  8767.  
  8768. {------------------------------------------------------------------------------
  8769.     Procedure: TCustomPlot.SetAsNormalClick
  8770.   Description: Defines the current view == Mins and Maxes of axes, as the Normal view.
  8771.        Author: Mat Ballard
  8772.  Date created: 08/12/2000
  8773. Date modified: 08/12/2000 by Mat Ballard
  8774.       Purpose: Zoom == Axis Min/Max management
  8775.  Known Issues:
  8776.  ------------------------------------------------------------------------------}
  8777. procedure TCustomPlot.SetAsNormalClick(Sender: TObject);
  8778. var
  8779.   i: Integer;
  8780.   pTheAxis: TAxis;
  8781. begin
  8782.   for i := 0 to FAxisList.Count-1 do
  8783.   begin
  8784.     pTheAxis := TAxis(FAxisList.Items[i]);
  8785.     pTheAxis.ZoomIntercept := pTheAxis.Intercept;
  8786.     pTheAxis.ZoomMin := pTheAxis.Min;
  8787.     pTheAxis.ZoomMax := pTheAxis.Max;
  8788.   end;
  8789.   FPlotPopUpMenu.Items[Ord(mnuView)].Items[Ord(mnuNormal)].Enabled := TRUE;
  8790. end;
  8791.  
  8792. {------------------------------------------------------------------------------
  8793.     Procedure: TCustomPlot.NormalViewClick
  8794.   Description: Zooms to the Normal view
  8795.        Author: Mat Ballard
  8796.  Date created: 08/12/2000
  8797. Date modified: 08/12/2000 by Mat Ballard
  8798.       Purpose: Zoom == Axis Min/Max management
  8799.  Known Issues:
  8800.  ------------------------------------------------------------------------------}
  8801. procedure TCustomPlot.NormalViewClick(Sender: TObject);
  8802. var
  8803.   i: Integer;
  8804.   pTheAxis: TAxis;
  8805. begin
  8806.   for i := 0 to FAxisList.Count-1 do
  8807.   begin
  8808.     pTheAxis := TAxis(FAxisList.Items[i]);
  8809.     if (pTheAxis.ZoomMin < pTheAxis.ZoomMax) then
  8810.     begin
  8811.       pTheAxis.Min := pTheAxis.ZoomMin;
  8812.       pTheAxis.Max := pTheAxis.ZoomMax;
  8813.       pTheAxis.Intercept := pTheAxis.ZoomIntercept;
  8814.     end;
  8815.   end;
  8816. end;
  8817.  
  8818. {------------------------------------------------------------------------------
  8819.     Procedure: TCustomPlot.ManualZoomClick
  8820.   Description: Manually Zooms In
  8821.        Author: Mat Ballard
  8822.  Date created: 02/25/2000
  8823. Date modified: 02/25/2000 by Mat Ballard
  8824.       Purpose: Runs the ZoomForm and adjusts Axes accordingly
  8825.  Known Issues:
  8826.  ------------------------------------------------------------------------------}
  8827. procedure TCustomPlot.ManualZoomClick(Sender: TObject);
  8828. var
  8829.   ZoomForm: TZoomForm;
  8830. begin
  8831.   ZoomForm := TZoomForm.Create(Self);
  8832.   ZoomForm.ThePlot := Self;
  8833.   ZoomForm.XMinNEdit.AsReal := FXAxis.Min;
  8834.   ZoomForm.XMaxNEdit.AsReal := FXAxis.Max;
  8835.   ZoomForm.YMinNEdit.AsReal := FYAxis.Min;
  8836.   ZoomForm.YMaxNEdit.AsReal := FYAxis.Max;
  8837.  
  8838.   ZoomForm.HelpFile := FHelpFile;
  8839.  
  8840.   if (ZoomForm.ShowModal = mrOK) then
  8841.     ApplyZoom(ZoomForm);
  8842.  
  8843.   ZoomForm.Free;
  8844.   Refresh;
  8845. end;
  8846.  
  8847. {------------------------------------------------------------------------------
  8848.     Procedure: TCustomPlot.ApplyZoom
  8849.   Description: Manually Zooms In
  8850.        Author: Mat Ballard
  8851.  Date created: 02/25/2000
  8852. Date modified: 02/25/2000 by Mat Ballard
  8853.       Purpose: Runs the ZoomForm and adjusts Axes accordingly
  8854.  Known Issues:
  8855.  ------------------------------------------------------------------------------}
  8856. procedure TCustomPlot.ApplyZoom(Sender: TObject);
  8857. var
  8858.   i,
  8859.   PixelYMin,
  8860.   PixelYMax: Integer;
  8861.   pTheYAxis: TAxis;
  8862. begin
  8863.   FXAxis.Min := TZoomForm(Sender).XMinNEdit.AsReal;
  8864.   FXAxis.Max := TZoomForm(Sender).XMaxNEdit.AsReal;
  8865.   FYAxis.Min := TZoomForm(Sender).YMinNEdit.AsReal;
  8866.   FYAxis.Max := TZoomForm(Sender).YMaxNEdit.AsReal;
  8867.   PixelYMin := FYAxis.FofY(FYAxis.Min);
  8868.   PixelYMax := FYAxis.FofY(FYAxis.Max);
  8869.   for i := 2 to FAxisList.Count-1 do
  8870.   begin
  8871.     pTheYAxis := TAxis(FAxisList[i]);
  8872.     pTheYAxis.Min := pTheYAxis.YofF(PixelYMin);
  8873.     pTheYAxis.Max := pTheYAxis.YofF(PixelYMax);
  8874.   end;
  8875.   Refresh;
  8876. end;
  8877.  
  8878. {------------------------------------------------------------------------------
  8879.     Procedure: TCustomPlot.ZoomOutClick
  8880.   Description: Zooms out after Zooming In
  8881.        Author: Mat Ballard
  8882.  Date created: 02/25/2000
  8883. Date modified: 02/25/2000 by Mat Ballard
  8884.       Purpose: Resets the axes Min and Max values to those of the Axis
  8885.  Known Issues:
  8886.  ------------------------------------------------------------------------------}
  8887. procedure TCustomPlot.ZoomOutClick(Sender: TObject);
  8888. var
  8889.   i: Integer;
  8890.   pSeries: TSeries;
  8891. begin
  8892.   FXAxis.Min := FSeriesList.Xmin;
  8893.   FXAxis.Max := FSeriesList.Xmax;
  8894.   FYAxis.Intercept := FXAxis.Min;
  8895. {  for i := 1 to FAxisList.Count-1 do
  8896.   begin
  8897.     TAxis(FAxisList[i]).Visible := FALSE;
  8898.   end;}
  8899.  
  8900.   case FPlotType of
  8901.     ptXY, ptMultiple:
  8902.       begin
  8903.         for i := 0 to FSeriesList.Count-1 do
  8904.         begin
  8905.           pSeries := FSeriesList[i];
  8906.           pSeries.YAxis.Min := pSeries.YMin;
  8907.           pSeries.YAxis.Max := pSeries.YMax;
  8908.           {if (pSeries.YAxis.Min > Round(pSeries.YMin - 0.999)) then
  8909.             pSeries.YAxis.Min := Round(pSeries.YMin - 0.999);
  8910.           if (pSeries.YAxis.Max < Round(pSeries.YMax + 0.999)) then
  8911.             pSeries.YAxis.Max := Round(pSeries.YMax + 0.999);}
  8912.         end;
  8913.       end;
  8914.  
  8915.     ptError, ptBubble:
  8916.       begin
  8917.         for i := 0 to FSeriesList.Count-1 do
  8918.         begin
  8919.           if ((i mod 2) = 0) then
  8920.           begin {odd series are just error - not values}
  8921.             pSeries := FSeriesList[i];
  8922.             pSeries.YAxis.Min := pSeries.YMin;
  8923.             pSeries.YAxis.Max := pSeries.YMax;
  8924.             {if (pSeries.YAxis.Min > Round(FSeriesList.YErrorMin - 0.999)) then
  8925.               pSeries.YAxis.Min := Round(FSeriesList.YErrorMin - 0.999);
  8926.             if (pSeries.YAxis.Max < Round(FSeriesList.YErrorMax + 0.999)) then
  8927.               pSeries.YAxis.Max := Round(FSeriesList.YErrorMax + 0.999);}
  8928.           end;
  8929.         end;
  8930.       end;
  8931.  
  8932.     ptColumn:
  8933.       begin
  8934.         for i := 1 to FAxisList.Count-1 do
  8935.           TAxis(FAxisList[i]).Min := 0;
  8936.         for i := 0 to FSeriesList.Count-1 do
  8937.         begin
  8938.           pSeries := FSeriesList[i];
  8939.           if (pSeries.YAxis.Max < Round(pSeries.YMax + 0.999)) then
  8940.             pSeries.YAxis.Max := Round(pSeries.YMax + 0.999);
  8941.         end;
  8942.       end;
  8943.  
  8944.     ptStack:
  8945.       begin
  8946.         YAxis.Min := 0;
  8947.         if (FSeriesList.TotalNoPts > 0) then
  8948.           YAxis.Max := Round(FSeriesList.Count * FSeriesList.Ymax + 0.999);
  8949.       end;
  8950.  
  8951.     ptNormStack:
  8952.       begin
  8953.         for i := 1 to FAxisList.Count-1 do
  8954.         begin
  8955.           TAxis(FAxisList[i]).Min := 0;
  8956.           TAxis(FAxisList[i]).Max := 100;
  8957.         end;
  8958.       end;
  8959.       
  8960.     ptPolar:
  8961.       begin
  8962.         FXAxis.Min := Round(FSeriesList.Xmin - 0.999);
  8963.         FXAxis.Max := Round(FSeriesList.Xmax + 0.999);
  8964.         FYAxis.Min := Round(FSeriesList.Ymin - 0.999);
  8965.         FYAxis.Max := Round(FSeriesList.Ymax + 0.999);
  8966.         if (FXAxis.Min > -FXAxis.Max) then
  8967.           FXAxis.Min := -FXAxis.Max;
  8968.         if (FXAxis.Max < -FXAxis.Min) then
  8969.           FXAxis.Max := -FXAxis.Min;
  8970.         if (FYAxis.Min > -FYAxis.Max) then
  8971.           FYAxis.Min := -FYAxis.Max;
  8972.         if (FYAxis.Max < -FYAxis.Min) then
  8973.           FYAxis.Max := -FYAxis.Min;
  8974.         FXAxis.Intercept := 0;
  8975.         FYAxis.Intercept := 0;
  8976.       end;
  8977.  
  8978.     ptLineContour:
  8979.       begin
  8980.         FContourStart := FSeriesList.Ymin;
  8981.         FContourInterval := (FSeriesList.Ymax - FContourStart) / 10;
  8982.       end;
  8983.  
  8984.     pt3DContour, pt3DWire, pt3DColumn:
  8985.       begin
  8986.         FYAxis.Min := FSeriesList.Ymin;
  8987.         FYAxis.Max := FSeriesList.Ymax;
  8988.         FZAxis.Min := FSeriesList.Zmin;
  8989.         FZAxis.Max := FSeriesList.Zmax;
  8990.       end;
  8991.   end; {case}
  8992.   FXAxis.Intercept := FYAxis.Min;
  8993.  
  8994.   DestroyPageButtons;
  8995.  
  8996.   DoStyleChange(Self);
  8997. end;
  8998.  
  8999. {------------------------------------------------------------------------------
  9000.     Procedure: TCustomPlot.CopyHTMLClick
  9001.   Description: copys the data as HTML
  9002.        Author: Mat Ballard
  9003.  Date created: 04/25/2000
  9004. Date modified: 04/25/2000 by Mat Ballard
  9005.       Purpose: ... in CF_TEXT format
  9006.  Known Issues:
  9007.  ------------------------------------------------------------------------------}
  9008. procedure TCustomPlot.CopyHTMLClick(Sender: TObject);
  9009. begin
  9010.   CopyHTML(CF_TEXT);
  9011. end;
  9012.  
  9013. {------------------------------------------------------------------------------
  9014.     Procedure: TCustomPlot.HandleClick
  9015.   Description: fires the OnClick event of the menuitem with Tag Tag
  9016.        Author: Mat Ballard
  9017.  Date created: 04/25/2000
  9018. Date modified: 04/25/2000 by Mat Ballard
  9019.       Purpose: allows the TPlotMenu component to function
  9020.  Known Issues:
  9021.  ------------------------------------------------------------------------------}
  9022. procedure TCustomPlot.HandleClick(Sender: TObject; TheTag: Integer);
  9023. var
  9024.   i, j: Integer;
  9025. begin
  9026. {needed to handle Mode and Direction:}
  9027.   FMenuTag := TheTag;
  9028.   if (GetIndicesFromTag(TheTag, i, j)) then
  9029. {$IFDEF COMPILER2_UP}
  9030.     if Assigned(FPlotPopUpMenu.Items[i].Items[j].OnClick) then
  9031. {$ENDIF}
  9032.       FPlotPopUpMenu.Items[i].Items[j].OnClick(Sender);
  9033. end;
  9034.  
  9035. {------------------------------------------------------------------------------
  9036.     Procedure: TCustomPlot.GetIndicesFromTag
  9037.   Description: Gets the i and j indices from the Tag
  9038.        Author: Mat Ballard
  9039.  Date created: 05/25/2000
  9040. Date modified: 05/25/2000 by Mat Ballard
  9041.       Purpose: interfacing with external components
  9042.  Known Issues:
  9043.  ------------------------------------------------------------------------------}
  9044. function TCustomPlot.GetIndicesFromTag(TheTag: Integer; var i, j: Integer): Boolean;
  9045. var
  9046.   MenuIndex: Integer;
  9047.   TheResult: Boolean;
  9048. begin
  9049. {TPlotToolBar throws some strange tags at this function:
  9050.   if (TheTag <= TAG_BASE) then raise
  9051.     ERangeError.CreateFmt('GetIndicesFromTag: ' + sInvalidTag, [Tag]);}
  9052.  
  9053.   TheResult := FALSE;
  9054.  
  9055.   MenuIndex := TheTag - TAG_BASE - Ord(High(TMainMenus)){mnuCalc} - 2;
  9056.   if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TFileMenus)){mnuPrint})) then
  9057.   begin
  9058.     i := 0;
  9059.     j := MenuIndex;
  9060.     TheResult := TRUE;
  9061.   end
  9062.   else
  9063.   begin
  9064.     MenuIndex := MenuIndex - Ord(High(TFileMenus)){mnuPrint} - 1;
  9065.     if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TEditMenus)))) then
  9066.     begin
  9067.       i := 1;
  9068.       j := MenuIndex;
  9069.       TheResult := TRUE;
  9070.     end
  9071.     else
  9072.     begin
  9073.       MenuIndex := MenuIndex - Ord(High(TEditMenus)){mnuEditProperties} - 1;
  9074.       if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TViewMenus)))) then
  9075.       begin
  9076.         i := 2;
  9077.         j := MenuIndex;
  9078.         TheResult := TRUE;
  9079.       end
  9080.       else
  9081.       begin
  9082.         MenuIndex := MenuIndex - Ord(High(TViewMenus)) - 1;
  9083.         if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TCalcMenus)))) then
  9084.         begin
  9085.           i := 3;
  9086.           j := MenuIndex;
  9087.           TheResult := TRUE;
  9088. {$IFDEF FINANCE}
  9089.         end
  9090.         else
  9091.         begin
  9092.           MenuIndex := MenuIndex - Ord(High(TCalcMenus)) - 1;
  9093.           if ((MenuIndex >= 0) and (MenuIndex <= Ord(High(TFinanceMenus)))) then
  9094.           begin
  9095.             i := 4;
  9096.             j := MenuIndex;
  9097.             TheResult := TRUE;
  9098.           end;
  9099. {$ENDIF}
  9100.         end;
  9101.       end;
  9102.     end;
  9103.   end;
  9104.   GetIndicesFromTag := TheResult;
  9105. {$IFDEF DELPHI3_UP}
  9106.   if (TheResult) then
  9107.     Assert(FPlotPopUpMenu.Items[i].Items[j].Tag = TheTag,
  9108.       'TCustomPlot.GetIndicesFromTag: ' + sTagNotMatch);
  9109. {$ENDIF}
  9110. end;
  9111.  
  9112. {------------------------------------------------------------------------------
  9113.     Procedure: TCustomPlot.DisplaceClick
  9114.   Description: runs the "Displacement" dialog box
  9115.        Author: Mat Ballard
  9116.  Date created: 04/25/2000
  9117. Date modified: 04/25/2000 by Mat Ballard
  9118.       Purpose: responds to "Displace" menu selection
  9119.  Known Issues:
  9120.  ------------------------------------------------------------------------------}
  9121. procedure TCustomPlot.DisplaceClick(Sender: TObject);
  9122. begin
  9123.   if (GetSeriesFromUser) then
  9124.   begin
  9125.     pSeries.Displace(FHelpFile);
  9126.     DoStyleChange(Self);
  9127.   end;
  9128.   ZeroScreenStuff;
  9129. end;
  9130.  
  9131. {------------------------------------------------------------------------------
  9132.     Procedure: TCustomPlot.ZoomInClick
  9133.   Description: Zooms in using the mouse
  9134.        Author: Mat Ballard
  9135.  Date created: 04/25/2000
  9136. Date modified: 05/30/2001 by Mat Ballard
  9137.       Purpose: responds to "Zoom In" menu selection
  9138.  Known Issues:
  9139.  ------------------------------------------------------------------------------}
  9140. procedure TCustomPlot.ZoomInClick(Sender: TObject);
  9141. var
  9142.   i: Integer;
  9143.   NewMin: Single;
  9144. begin
  9145.   if ((FScreenJob = sjRightDrag) or
  9146.       (FScreenJob = sjZoomIn)) then
  9147.   begin
  9148.     NewMin := FXAxis.XofF(Selection.Left);
  9149.     FXAxis.SetMinMaxFromSeries(NewMin, FXAxis.XofF(Selection.Right));
  9150.     for i := 1 to FAxisList.Count-1 do
  9151.     begin
  9152.       TAxis(FAxisList[i]).AutoScale := TRUE;
  9153.       NewMin := TAxis(FAxisList[i]).YofF(Selection.Bottom);
  9154.       FYAxis.SetMinMaxFromSeries(NewMin, TAxis(FAxisList[i]).YofF(Selection.Top));
  9155.     end;
  9156.     CreatePageButtons;
  9157.     ZeroScreenStuff;
  9158.   end
  9159.   else
  9160.   begin
  9161.     FInstructions.Clear;
  9162.     FInstructions.Add(sZoomInClick1);
  9163.     FScreenJob := sjZoomIn;
  9164.     DoStyleChange(Self);
  9165.   end;
  9166. end;
  9167.  
  9168. {------------------------------------------------------------------------------
  9169.     Procedure: TCustomPlot.DifferentiateClick
  9170.   Description: Replaces the selected Axis with its differential
  9171.        Author: Mat Ballard
  9172.  Date created: 04/25/2000
  9173. Date modified: 04/25/2000 by Mat Ballard
  9174.       Purpose: responds to "Differential" menu selection
  9175.  Known Issues:
  9176.  ------------------------------------------------------------------------------}
  9177. procedure TCustomPlot.DifferentiateClick(Sender: TObject);
  9178. begin
  9179.   if (GetSeriesFromUser) then
  9180.   begin
  9181.     pSeries.Differentiate;
  9182.     ZoomOutClick(Self);
  9183.   end;
  9184.   ZeroScreenStuff;
  9185. end;
  9186.  
  9187. {------------------------------------------------------------------------------
  9188.     Procedure: TCustomPlot.IntegrateClick
  9189.   Description: Replaces the selected Axis with its differential
  9190.        Author: Mat Ballard
  9191.  Date created: 04/25/2000
  9192. Date modified: 04/25/2000 by Mat Ballard
  9193.       Purpose: responds to "Integrate" menu selection
  9194.  Known Issues:
  9195.  ------------------------------------------------------------------------------}
  9196. procedure TCustomPlot.IntegrateClick(Sender: TObject);
  9197. begin
  9198.   if (GetSeriesFromUser) then
  9199.   begin
  9200.     pSeries.Integrate;
  9201.     ZoomOutClick(Self);
  9202.   end;
  9203.   ZeroScreenStuff;
  9204. end;
  9205.  
  9206. {------------------------------------------------------------------------------
  9207.     Procedure: TCustomPlot.IntegralClick
  9208.   Description: calculates the integral of the selected Series over a selected range
  9209.        Author: Mat Ballard
  9210.  Date created: 04/25/2000
  9211. Date modified: 05/30/2001 by Mat Ballard
  9212.       Purpose: responds to "Integral" menu selection
  9213.  Known Issues:
  9214.  ------------------------------------------------------------------------------}
  9215. procedure TCustomPlot.IntegralClick(Sender: TObject);
  9216. var
  9217.   Msg: String;
  9218.   Sum,
  9219.   TheLeft,
  9220.   TheRight: Single;
  9221. begin
  9222.   if (GetSeriesFromUser) then
  9223.   begin
  9224.     if ((FScreenJob = sjRightDrag) or
  9225.         (FScreenJob = sjIntegral)) then
  9226.     begin
  9227.       TheLeft := FXAxis.XofF(Selection.Left);
  9228.       TheRight := FXAxis.XofF(Selection.Right);
  9229.       Sum := pSeries.Integral(TheLeft, TheRight);
  9230.       Msg := sIntegral1 + pSeries.Name + sFrom + CRLF;
  9231.       Msg := Msg + FXAxis.LabelToStrF(TheLeft) + sTo +
  9232.         FXAxis.LabelToStrF(TheRight);
  9233.       if (Length(FXAxis.Title.Units) > 0) then
  9234.         Msg := Msg + ' ' + FXAxis.Title.Units;
  9235.       Msg := Msg + sIs + CRLF +
  9236.         Format('%g', [Sum]);
  9237.       if ((Length(FXAxis.Title.Units) > 0) and
  9238.           (Length(pSeries.YAxis.Title.Units) > 0)) then
  9239.       begin
  9240.         Msg := Msg + ' (' + pSeries.YAxis.Title.Units + '.' +
  9241.           FXAxis.Title.Units + ')';
  9242.       end
  9243.       else if (Length(FXAxis.Title.Units) > 0) then
  9244.       begin
  9245.         Msg := Msg + ' (' + FXAxis.Title.Units + ')';
  9246.       end
  9247.       else if (Length(pSeries.YAxis.Title.Units) > 0) then
  9248.       begin
  9249.         Msg := Msg + ' (' + pSeries.YAxis.Title.Units + ')';
  9250.       end;
  9251.       ShowMessage(Msg);
  9252.       ClipBoard.AsText := Msg;
  9253.       ZeroScreenStuff;
  9254.     end
  9255.     else
  9256.     begin
  9257.       FScreenJob := sjIntegral;
  9258.       FInstructions.Clear;
  9259.       FInstructions.Add(sIntegral2);
  9260.       DoStyleChange(Self);
  9261.     end;
  9262.   end;
  9263. end;
  9264.  
  9265. {------------------------------------------------------------------------------
  9266.      Function: TCustomPlot.GetClickAndDragDelay
  9267.   Description: standard property Get function
  9268.        Author: Mat Ballard
  9269.  Date created: 04/25/2000
  9270. Date modified: 04/25/2000 by Mat Ballard
  9271.       Purpose: gets the value of the ClickAndDragDelay Property
  9272.  Return value: Integer
  9273.  Known Issues:
  9274.  ------------------------------------------------------------------------------}
  9275. function TCustomPlot.GetClickAndDragDelay: Integer;
  9276. begin
  9277.   GetClickAndDragDelay := MouseTimer.Interval;
  9278. end;
  9279.  
  9280. {------------------------------------------------------------------------------
  9281.     Procedure: TCustomPlot.ZeroScreenStuff
  9282.   Description: cleans up after a menu event handler - XXXClick
  9283.        Author: Mat Ballard
  9284.  Date created: 04/25/2000
  9285. Date modified: 04/25/2000 by Mat Ballard
  9286.       Purpose: mouse management
  9287.  Known Issues:
  9288.  ------------------------------------------------------------------------------}
  9289. procedure TCustomPlot.ZeroScreenStuff;
  9290. begin
  9291.   FScreenJob := sjNone;
  9292.   ClickedObjectType := soNone;
  9293.   pClickedObject := nil;
  9294.   SecondClickedObjectType := soNone;
  9295.   pSecondClickedObject := nil;
  9296.   TheSeries := -1;
  9297.   pSeries := nil;
  9298.   TheAxis := -1;
  9299.   pAxis := nil;
  9300.   FOnSelection := nil;
  9301.   FOnDualSelection := nil;
  9302.   Screen.Cursor := crDefault;
  9303. end;
  9304.  
  9305. {------------------------------------------------------------------------------
  9306.     Procedure: TCustomPlot.HighsClick
  9307.   Description: Calculates the Highs (peaks) and/or Lows (troughs) of a series
  9308.        Author: Mat Ballard
  9309.  Date created: 09/25/2000
  9310. Date modified: 09/25/2000 by Mat Ballard
  9311.       Purpose: data processing
  9312.  Known Issues:
  9313.  ------------------------------------------------------------------------------}
  9314. procedure TCustomPlot.HighsClick(Sender: TObject);
  9315. var
  9316.   OptionsDlg: TOptionsDlg;
  9317. begin
  9318.   if (GetSeriesFromUser) then
  9319.   begin
  9320.     OptionsDlg := TOptionsDlg.Create(nil);
  9321.     OptionsDlg.FormTitle := sHighLow1;
  9322.     OptionsDlg.Question := sHighLow2;
  9323.     OptionsDlg.OptionList.Add(sHighLow3);
  9324.     OptionsDlg.OptionList.Add(sHighLow4);
  9325.     OptionsDlg.OptionList.Add(sHighLow5);
  9326.     OptionsDlg.OptionList.Add(sHighLow6);
  9327.  
  9328.     case OptionsDlg.Execute of
  9329.       1: pSeries.ClearHighsLows;
  9330.       2:
  9331.         begin
  9332.           pSeries.FindHighsLows(0, pSeries.NoPts, 5);
  9333.           pSeries.HighLow := pSeries.HighLow + [hlHigh];
  9334.         end;
  9335.       3:
  9336.         begin
  9337.           pSeries.FindHighsLows(0, pSeries.NoPts, 5);
  9338.           pSeries.HighLow := pSeries.HighLow + [hlLow];
  9339.         end;
  9340.       4:
  9341.         begin
  9342.           pSeries.FindHighsLows(0, pSeries.NoPts, 5);
  9343.           pSeries.HighLow := pSeries.HighLow + [hlLow, hlHigh];
  9344.         end;
  9345.     end;
  9346.  
  9347.     OptionsDlg.Free;
  9348.  
  9349.     DoStyleChange(Self);
  9350.   end;
  9351.   ZeroScreenStuff;
  9352. end;
  9353.  
  9354. {------------------------------------------------------------------------------
  9355.     Procedure: TCustomPlot.MovingAverageClick
  9356.   Description: Calculates and displays the Moving Average of a series
  9357.        Author: Mat Ballard
  9358.  Date created: 09/25/2000
  9359. Date modified: 09/25/2000 by Mat Ballard
  9360.       Purpose: data smoothing
  9361.  Known Issues:
  9362.  ------------------------------------------------------------------------------}
  9363. procedure TCustomPlot.MovingAverageClick(Sender: TObject);
  9364. var
  9365.   Span: Integer;
  9366.   SpanStr: String;
  9367. begin
  9368.   if (GetSeriesFromUser) then
  9369.   begin
  9370.     SpanStr := '10';
  9371.     if (InputQuery(sMovingAverage1, sMovingAverage2, SpanStr)) then
  9372.     begin
  9373.       try
  9374.         Span := StrToInt(SpanStr);
  9375.         pSeries.MovingAverage(Span);
  9376.       except
  9377.         ShowMessage(sMovingAverage3);
  9378.       end;
  9379.     end;
  9380.     DoStyleChange(Self);
  9381.   end;
  9382.   ZeroScreenStuff;
  9383. end;
  9384.  
  9385. {------------------------------------------------------------------------------
  9386.     Procedure: TCustomPlot.AverageClick
  9387.   Description: Calculates the Average of a series over a range
  9388.        Author: Mat Ballard
  9389.  Date created: 09/25/2000
  9390. Date modified: 05/30/2001 by Mat Ballard
  9391.       Purpose: data processing
  9392.  Known Issues:
  9393.  ------------------------------------------------------------------------------}
  9394. procedure TCustomPlot.AverageClick(Sender: TObject);
  9395. var
  9396.   Msg: String;
  9397.   Sum,
  9398.   TheLeft,
  9399.   TheRight: Single;
  9400. begin
  9401.   if (GetSeriesFromUser) then
  9402.   begin
  9403.     if ((FScreenJob = sjRightDrag) or
  9404.         (FScreenJob = sjAverage)) then
  9405.     begin
  9406.       TheLeft := FXAxis.XofF(Selection.Left);
  9407.       TheRight := FXAxis.XofF(Selection.Right);
  9408.       Sum := pSeries.Average(TheLeft, TheRight);
  9409.       Msg := sAverage1 + pSeries.Name + sFrom + CRLF;
  9410.       Msg := Msg + FXAxis.LabelToStrF(TheLeft) + sTo +
  9411.         FXAxis.LabelToStrF(TheRight);
  9412.       if (Length(FXAxis.Title.Units) > 0) then
  9413.         Msg := Msg + ' ' + FXAxis.Title.Units;
  9414.       Msg := Msg + sIs + CRLF +
  9415.         Format('%g', [Sum]);
  9416.       if (Length(pSeries.YAxis.Title.Units) > 0) then
  9417.       begin
  9418.         Msg := Msg + ' (' + pSeries.YAxis.Title.Units + ')';
  9419.       end;
  9420.       ShowMessage(Msg);
  9421.       ClipBoard.AsText := Msg;
  9422.       ZeroScreenStuff;
  9423.     end
  9424.     else
  9425.     begin
  9426.       FScreenJob := sjAverage;
  9427.       FInstructions.Clear;
  9428.       FInstructions.Add(sAverage2);
  9429.       DoStyleChange(Self);
  9430.     end;
  9431.   end;
  9432. end;
  9433.  
  9434. {------------------------------------------------------------------------------
  9435.     Procedure: TCustomPlot.LinearizeClick
  9436.   Description: Linearizes Y data of a series over a range
  9437.        Author: Mat Ballard
  9438.  Date created: 05/30/2001
  9439. Date modified: 05/30/2001 by Mat Ballard
  9440.       Purpose: data processing
  9441.  Known Issues:
  9442.  ------------------------------------------------------------------------------}
  9443. procedure TCustomPlot.LinearizeClick(Sender: TObject);
  9444. var
  9445.   TheLeft,
  9446.   TheRight: Single;
  9447. begin
  9448.   if (GetSeriesFromUser) then
  9449.   begin
  9450.     if ((FScreenJob = sjRightDrag) or
  9451.         (FScreenJob = sjLinearize)) then
  9452.     begin
  9453.       TheLeft := FXAxis.XofF(Selection.Left);
  9454.       TheRight := FXAxis.XofF(Selection.Right);
  9455.       pSeries.Linearize(TheLeft, TheRight);
  9456.       ZeroScreenStuff;
  9457.       Refresh;
  9458.     end
  9459.     else
  9460.     begin
  9461.       FScreenJob := sjLinearize;
  9462.       FInstructions.Clear;
  9463.       FInstructions.Add(sLinearizeClick1);
  9464.       DoStyleChange(Self);
  9465.     end;
  9466.   end;
  9467. end;
  9468.  
  9469. {------------------------------------------------------------------------------
  9470.     Procedure: TCustomPlot.ZeroClick
  9471.   Description: Calculates the Zero of a series over a range
  9472.        Author: Mat Ballard
  9473.  Date created: 05/30/2001
  9474. Date modified: 05/30/2001 by Mat Ballard
  9475.       Purpose: data processing
  9476.  Known Issues:
  9477.  ------------------------------------------------------------------------------}
  9478. procedure TCustomPlot.ZeroClick(Sender: TObject);
  9479. var
  9480.   TheLeft,
  9481.   TheRight: Single;
  9482. begin
  9483.   if (GetSeriesFromUser) then
  9484.   begin
  9485.     if ((FScreenJob = sjRightDrag) or
  9486.         (FScreenJob = sjZero)) then
  9487.     begin
  9488.       TheLeft := FXAxis.XofF(Selection.Left);
  9489.       TheRight := FXAxis.XofF(Selection.Right);
  9490.       pSeries.Zero(TheLeft, TheRight);
  9491.       ZeroScreenStuff;
  9492.       Refresh;
  9493.     end
  9494.     else
  9495.     begin
  9496.       FScreenJob := sjZero;
  9497.       FInstructions.Clear;
  9498.       FInstructions.Add(sZeroClick1);
  9499.       DoStyleChange(Self);
  9500.     end;
  9501.   end;
  9502. end;
  9503.  
  9504. {------------------------------------------------------------------------------
  9505.     Procedure: TCustomPlot.NewYAxisClick
  9506.   Description: Adds a new axis, based on either the selected or last axis.
  9507.        Author: Mat Ballard
  9508.  Date created: 06/12/2000
  9509. Date modified: 06/12/2000 by Mat Ballard
  9510.       Purpose: axis management
  9511.  Known Issues:
  9512.  ------------------------------------------------------------------------------}
  9513. procedure TCustomPlot.NewYAxisClick(Sender: TObject);
  9514. var
  9515.   TheTemplate: Integer;
  9516.   NewAxis: TAxis;
  9517. begin
  9518. {has the user already selected an object ?}
  9519. {see GetTheClickedObject and ZeroScreenStuff}
  9520.   TheTemplate := TheAxis;
  9521.   if (TheTemplate <= 0) then
  9522.     TheTemplate := FAxisList.Count - 1;
  9523. {NB: there is only ONE X Axis, otherwise things get TOO complicated,
  9524.  so if the user right-clicks on the X Axis, it is effectively ignored}
  9525.  
  9526.   NewAxis := TAxis.Create(Self);
  9527.   FAxisList.Add(NewAxis);
  9528.   NewAxis.Assign(TAxis(FAxisList[TheTemplate]));
  9529.   NewAxis.OnChange := DoStyleChange;
  9530.  
  9531. {Move the new axis to the right:}
  9532.   if (FAxisList.Count = 3) then
  9533.   begin
  9534. {this new one is a secondary axis:}
  9535.     NewAxis.AxisType := atSecondary;
  9536.     NewAxis.Intercept := FXAxis.Max;
  9537.     NewAxis.TickDirection := orRight;
  9538.     NewAxis.Title.Orientation := orRight;
  9539.   end
  9540.   else
  9541.   begin
  9542.     NewAxis.AxisType := atTertiary;
  9543. {place the new axis half-way between the last and the right hand side:}
  9544.     NewAxis.Intercept := FXAxis.XofF((NewAxis.MidX + Width) div 2);
  9545.   end;
  9546.  
  9547. {if this over-runs the panel width, then wrap around:}
  9548.   if (NewAxis.Left > Width) then
  9549.     NewAxis.Left := NewAxis.Left - Width;
  9550.  
  9551. {... and rename it:}
  9552.   NewAxis.Name := sCopy + ' ' + sOf + ' ' + NewAxis.Name;
  9553.   NewAxis.Title.Caption := sCopy + ' ' + sOf + ' ' + NewAxis.Title.Caption;
  9554.   NewAxis.Tag := Ord(soYAxis);
  9555.   NewAxis.Labels.Tag := Ord(soYAxisLabel);
  9556.   NewAxis.Title.Tag := Ord(soYAxisTitle);
  9557.  
  9558. {add this New Y Axis to the ScreenObjectList:}
  9559.   ScreenObjectList.Insert(Ord(soLeftBorder), NewAxis.Labels);
  9560.   ScreenObjectList.Insert(Ord(soLeftBorder), NewAxis.Title);
  9561.   ScreenObjectList.Insert(Ord(soLeftBorder), NewAxis);
  9562.   //Inc(NoBasicScreenObjects, 3);
  9563. {note that we insert: we do this in order to make Y Axes be found before
  9564.  borders and series.}
  9565.  
  9566. {re-initialize:}
  9567.   ZeroScreenStuff;
  9568. {we need to call re-size to force a SetAxisDimensions:}
  9569.   Resize;
  9570.   DoStyleChange(Self);
  9571. end;
  9572.  
  9573. {------------------------------------------------------------------------------
  9574.     Procedure: TCustomPlot.DeleteAxisClick
  9575.   Description: Deletes an axis
  9576.        Author: Mat Ballard
  9577.  Date created: 06/12/2000
  9578. Date modified: 06/12/2000 by Mat Ballard
  9579.       Purpose: axis management
  9580.  Known Issues:
  9581.  ------------------------------------------------------------------------------}
  9582. procedure TCustomPlot.DeleteAxisClick(Sender: TObject);
  9583. begin
  9584.   if (GetAxisFromUser(2)) then
  9585.     DeleteAxis(TheAxis, TRUE);
  9586. end;
  9587.  
  9588. {------------------------------------------------------------------------------
  9589.     Procedure: TCustomPlot.DeleteAxis
  9590.   Description: Deletes the selected axis
  9591.        Author: Mat Ballard
  9592.  Date created: 04/25/2000
  9593. Date modified: 04/25/2000 by Mat Ballard
  9594.       Purpose: axis management
  9595.  Known Issues:
  9596.  ------------------------------------------------------------------------------}
  9597. procedure TCustomPlot.DeleteAxis(Index: Integer; Confirm: Boolean);
  9598. var
  9599.   pAxisToDelete: TAxis;
  9600. begin
  9601.   if ((Index <= 1) or
  9602.       (Index >= FAxisList.Count)) then raise
  9603.     ERangeError.CreateFmt(sDeleteAxis1, [Index, FAxisList.Count-1]);
  9604.  
  9605.   pAxisToDelete := TAxis(FAxisList[Index]);
  9606.  
  9607.   if (Confirm) then
  9608.   begin
  9609.     {Confirm := (IDNO = MessageBox(0,
  9610.       'Are you sure you want to delete' + pAxisToDelete.Title.Caption,
  9611.       'Delete Secondary Axis',
  9612.       MB_YESNO + MB_ICONQUESTION));}
  9613.     Confirm := (mrNo =
  9614.       MessageDlg(
  9615. {$IFDEF LINUX}
  9616.       sDeleteAxis2,
  9617. {$ENDIF}
  9618.         sDeleteAxis3 + pAxisToDelete.Title.Caption,
  9619.         mtWarning,
  9620.         [mbYes, mbNo],
  9621.         0));
  9622.   end;
  9623.  
  9624.   if (not Confirm) then
  9625.   begin
  9626. {remove this Y Axis from the ScreenObjectList:}
  9627.     ScreenObjectList.Delete(ScreenObjectList.IndexOf(pAxisToDelete));
  9628.     ScreenObjectList.Delete(ScreenObjectList.IndexOf(pAxisToDelete.Title));
  9629.     ScreenObjectList.Delete(ScreenObjectList.IndexOf(pAxisToDelete.Labels));
  9630.     //Dec(NoBasicScreenObjects, 3);
  9631. {remove this Y Axis from the AxisList:}
  9632.     FAxisList.Delete(Index);
  9633. {and remove it:}
  9634.     pAxisToDelete.Free;
  9635.     DoStyleChange(Self);
  9636.   end;
  9637. end;
  9638.  
  9639. {$IFDEF FINANCE}
  9640. {------------------------------------------------------------------------------
  9641.     Procedure: TCustomPlot.ADLClick
  9642.   Description: This runs the ADL financial calculation
  9643.        Author: Mat Ballard
  9644.  Date created: 07/25/2001
  9645. Date modified: 07/25/2001 by Mat Ballard
  9646.       Purpose: standard Financial menu item event handler
  9647.  Known Issues:
  9648.  ------------------------------------------------------------------------------}
  9649. procedure TCustomPlot.ADLClick(Sender: TObject);
  9650. begin
  9651.   ShowMessage('Sorry - Financial calculations are not yet enabled !');
  9652. end;
  9653. {$ENDIF}
  9654.  
  9655. {------------------------------------------------------------------------------
  9656.      Function: TCustomPlot.GetNoSeries
  9657.   Description: standard property Get function
  9658.        Author: Mat Ballard
  9659.  Date created: 25/25/2000
  9660. Date modified: 25/25/2000 by Mat Ballard
  9661.       Purpose: gets the number of Series
  9662.  Return Value: integer
  9663.  Known Issues:
  9664.  ------------------------------------------------------------------------------}
  9665. function TCustomPlot.GetNoSeries: Word;
  9666. begin
  9667.   GetNoSeries := FSeriesList.Count;
  9668. end;
  9669.  
  9670. {------------------------------------------------------------------------------
  9671.      Function: TCustomPlot.GetNoYAxes
  9672.   Description: standard property Get function
  9673.        Author: Mat Ballard
  9674.  Date created: 06/25/2000
  9675. Date modified: 06/25/2000 by Mat Ballard
  9676.       Purpose: gets the number of Y Axes
  9677.  Return Value: integer
  9678.  Known Issues:
  9679.  ------------------------------------------------------------------------------}
  9680. function TCustomPlot.GetNoYAxes: Integer;
  9681. begin
  9682.   GetNoYAxes := FAxisList.Count-1;
  9683. end;
  9684.  
  9685. {------------------------------------------------------------------------------
  9686.     Procedure: TCustomPlot.SetNoYAxes
  9687.   Description: standard property Set procedure
  9688.        Author: Mat Ballard
  9689.  Date created: 04/25/2000
  9690. Date modified: 04/25/2000 by Mat Ballard
  9691.       Purpose: sets the number of Y Axes
  9692.  Known Issues: it is a fairly brutal way of setting the number of Y Axes
  9693.  ------------------------------------------------------------------------------}
  9694. procedure TCustomPlot.SetNoYAxes(Value: Integer);
  9695. var
  9696.   i: Integer;
  9697. begin
  9698.   if (Value < 1) then exit;
  9699.  
  9700.   if (Value = FAxisList.Count-1) then exit;
  9701.  
  9702.   if (Value > 15) then raise
  9703.     EComponentError.CreateFmt(sSetNoYAxes1, [Value]);
  9704.  
  9705.   if (Value < FAxisList.Count-1) then
  9706.   begin
  9707. {we need to delete some axes:}
  9708.     for i := FAxisList.Count-1 downto Value+1 do
  9709.     begin
  9710.       DeleteAxis(i, FALSE);
  9711.     end;
  9712.   end
  9713.   else
  9714.   begin
  9715. {in order to avoid creating an extra axis when a 3D plot is loaded:}
  9716.     if not (csLoading in ComponentState) then
  9717. {add some axes:}
  9718.       for i := FAxisList.Count-1 to Value-1 do
  9719.       begin
  9720.         NewYAxisClick(Self);
  9721.       end;
  9722.   end;
  9723. end;
  9724.  
  9725. {------------------------------------------------------------------------------
  9726.     Procedure: TCustomPlot.SetPlotType
  9727.   Description: standard property Set procedure
  9728.        Author: Mat Ballard
  9729.  Date created: 09/20/2000
  9730. Date modified: 01/16/2001 by Mat Ballard
  9731.       Purpose: sets the PlotType property
  9732.  Known Issues: under development
  9733.  ------------------------------------------------------------------------------}
  9734. procedure TCustomPlot.SetPlotType(Value: TPlotType);
  9735. var
  9736.   i: Integer;
  9737.   OldIgnoreChanges: Boolean;
  9738.  
  9739.   procedure AddZAxis;
  9740.   begin
  9741.     FZAxis := TAngleAxis.Create(Self);
  9742.     FZAxis.AxisType := atZ;
  9743.     FZAxis.Tag := Ord(soZAxis);
  9744.     FZAxis.FireEvents := FALSE;
  9745.     FZAxis.Name := 'Z';
  9746.     FZAxis.Title.Caption := 'Z-' + sAxis;
  9747.     {FZAxis.Left := FXAxis.Left;
  9748.     FZAxis.Top := FXAxis.MidY;}
  9749.     FZAxis.Length := FXAxis.Width div 3;
  9750.     FAxisList.Add(FZAxis);
  9751.     //ScreenObjectList.Add(FZAxis);
  9752.     ScreenObjectList.Items[Ord(soZAxis)] := FZAxis;
  9753.     ScreenObjectList.Items[Ord(soZAxisTitle)] := FZAxis.Title;
  9754.     ScreenObjectList.Items[Ord(soZAxisLabel)] := FZAxis.Labels;
  9755.     FBorder.Left := Self.Width div 3;
  9756.     FBorder.BottomGap := Self.Height div 3;
  9757.     FZAxis.OnChange := DoStyleChange;
  9758.   end;
  9759.   
  9760.   procedure RemoveZAxis;
  9761.   begin
  9762.     FZAxis.OnChange := nil;
  9763.     FAxisList.Remove(FZAxis);
  9764.     ScreenObjectList.Items[Ord(soZAxis)] := nil;
  9765.     ScreenObjectList.Items[Ord(soZAxisTitle)] := nil;
  9766.     ScreenObjectList.Items[Ord(soZAxisLabel)] := nil;
  9767.     //Dec(NoBasicScreenObjects);
  9768.     FZAxis.Free;
  9769.     FZAxis := nil;
  9770.   end;
  9771.  
  9772. begin
  9773.   if (FPlotType = Value) then exit;
  9774.  
  9775.   OldIgnoreChanges := IgnoreChanges;
  9776.   IgnoreChanges := TRUE;
  9777.  
  9778.   if (FZAxis <> nil) then
  9779.     if (Value < pt3DContour) then
  9780.       RemoveZAxis;
  9781.  
  9782.   if (csDesigning in ComponentState) then
  9783.     NoSeries := 2;
  9784.  
  9785.   FPlotType := Value;
  9786.  
  9787. {clean up axes:}  
  9788.   for i := 0 to FAxisList.Count-1 do
  9789.   begin
  9790.     TAxis(FAxisList.Items[i]).FireEvents := FALSE;
  9791.     TAxis(FAxisList.Items[i]).Visible := TRUE;
  9792.   end;
  9793.   FYAxis.Title.Visible := TRUE;
  9794.   FXAxis.Title.Alignment := taCenter;
  9795.  
  9796. {clear previous Series pen settings:}
  9797.   for i := 0 to FSeriesList.Count-1 do
  9798.   begin
  9799.     Series[i].Pen.Width := 1;
  9800.     Series[i].Symbol := syNone;
  9801.   end;
  9802.  
  9803. {re-scale the primary X Axis:}
  9804.   if (FSeriesList.TotalNoPts > 0) then
  9805.   begin
  9806.     if (FSeriesList.Xmin >= 0) then
  9807.       XAxis.Min := 0
  9808.     else
  9809.       XAxis.Min := Round(FSeriesList.Xmin - 0.999);
  9810.     XAxis.Max := Round(FSeriesList.Xmax + 0.999);
  9811.   end;
  9812.  
  9813. {re-scale the primary Y Axis:}
  9814.   if (FSeriesList.TotalNoPts > 0) then
  9815.   begin
  9816.     if (FSeriesList.Ymin >= 0) then
  9817.       YAxis.Min := 0
  9818.     else
  9819.       YAxis.Min := Round(FSeriesList.Ymin - 0.999);
  9820.     YAxis.Max := Round(FSeriesList.Ymax + 0.999);
  9821.   end;
  9822.  
  9823.   FLegend.Visible := TRUE;
  9824.  
  9825.   case FPlotType of
  9826.     ptXY: ;
  9827.  
  9828.     ptError:
  9829.       begin
  9830.         {if (csDesigning in ComponentState) then
  9831.           MakeDummyData(20);}
  9832.         i := 0;
  9833.         while (i <= FSeriesList.Count-2) do
  9834.         begin
  9835.           Series[i].Symbol := TSymbol(1 + (i div 2) mod (Ord(High(TSymbol))-2));
  9836.           Inc(i, 2);
  9837.         end;
  9838.         if (FSeriesList.TotalNoPts > 0) then
  9839.         begin
  9840.           YAxis.Min := Round(FSeriesList.YErrorMin - 0.999);
  9841.           YAxis.Max := Round(FSeriesList.YErrorMax + 0.999);
  9842.         end;
  9843.       end;
  9844.  
  9845.     ptMultiple:
  9846.       begin
  9847.         for i := 0 to FSeriesList.Count-1 do
  9848.         begin
  9849.           Series[i].Pen.Width := 0;
  9850.           Series[i].Symbol := TSymbol(1 + i mod (Ord(High(TSymbol))-2));
  9851.         end;
  9852.       end;
  9853.  
  9854.     ptColumn: YAxis.Min := 0;
  9855.  
  9856.     ptStack:
  9857.       begin
  9858.         YAxis.Min := 0;
  9859.         if (FSeriesList.TotalNoPts > 0) then
  9860.           YAxis.Max := Round(FSeriesList.Count * FSeriesList.Ymax + 0.999);
  9861.       end;
  9862.  
  9863.     ptNormStack:
  9864.       begin
  9865.         YAxis.Min := 0;
  9866.         YAxis.Max := 100;
  9867.       end;
  9868.  
  9869.     ptPie:
  9870.       begin
  9871.         for i := 0 to FAxisList.Count-1 do
  9872.           TAxis(FAxisList.Items[i]).Visible := FALSE;
  9873.       end;
  9874.  
  9875.     ptPolar:
  9876.       begin
  9877.         if (FXAxis.Min > -FXAxis.Max) then
  9878.           FXAxis.Min := -FXAxis.Max;
  9879.         if (FXAxis.Max < -FXAxis.Min) then
  9880.           FXAxis.Max := -FXAxis.Min;
  9881.         if (FYAxis.Min > -FYAxis.Max) then
  9882.           FYAxis.Min := -FYAxis.Max;
  9883.         if (FYAxis.Max < -FYAxis.Min) then
  9884.           FYAxis.Max := -FYAxis.Min;
  9885.         FXAxis.Intercept := 0;
  9886.         FYAxis.Intercept := 0;
  9887.         FYAxis.Title.Visible := FALSE;
  9888.         FXAxis.Title.Alignment := taRightJustify;
  9889.       end;
  9890.  
  9891.     ptLineContour, ptContour:
  9892.       begin
  9893.         if (csDesigning in ComponentState) then
  9894.         begin
  9895.           NoSeries := 10;
  9896.           MakeDummyData(20);
  9897.         end;
  9898.         FLegend.Visible := FALSE;
  9899.       end;
  9900.  
  9901.     pt3DContour, pt3DWire, pt3DColumn{, pt3DSurface}:
  9902.       begin
  9903.         if (FZAxis = nil) then
  9904.           AddZAxis;
  9905.         if (csDesigning in ComponentState) then
  9906.         begin
  9907.           FBorder.Left := 3 * FBorder.Left div 2;
  9908.           FBorder.BottomGap := 3 * FBorder.BottomGap div 2; 
  9909.           NoSeries := 10;
  9910.           MakeDummyData(20);
  9911.         end;
  9912.         FLegend.Visible := FALSE;
  9913.       end;
  9914.   end;
  9915.  
  9916. {deal with axes:}
  9917.   SetAxisDimensions;
  9918.   for i := 0 to FAxisList.Count-1 do
  9919.   begin
  9920.     TAxis(FAxisList.Items[i]).Intercept := 0;
  9921.     TAxis(FAxisList.Items[i]).FireEvents := TRUE;
  9922.   end;
  9923.  
  9924.   SetDefaults;
  9925.   IgnoreChanges := OldIgnoreChanges;
  9926.  
  9927.   DoStyleChange(Self);
  9928. end;
  9929.  
  9930. {------------------------------------------------------------------------------
  9931.     Procedure: TCustomPlot.SetPolarRange
  9932.   Description: standard property Set procedure
  9933.        Author: Mat Ballard
  9934.  Date created: 09/20/2000
  9935. Date modified: 01/16/2001 by Mat Ballard
  9936.       Purpose: sets the PolarRange property
  9937.  Known Issues: under development
  9938.  ------------------------------------------------------------------------------}
  9939. procedure TCustomPlot.SetPolarRange(Value: Single);
  9940. begin
  9941.   if (FPolarRange = Value) then exit;
  9942.  
  9943.   FPolarRange := Value;
  9944.   DoStyleChange(Self);
  9945. end;
  9946.  
  9947. {------------------------------------------------------------------------------
  9948.     Procedure: TCustomPlot.SetPopupOptions
  9949.   Description: standard property Set procedure
  9950.        Author: Mat Ballard
  9951.  Date created: 09/25/2000
  9952. Date modified: 09/25/2000 by Mat Ballard
  9953.       Purpose: sets the PopupOptions property, and informs any TPlotMenu and
  9954.                TPlotToolBar of the change
  9955.  Known Issues:
  9956.  ------------------------------------------------------------------------------}
  9957. procedure TCustomPlot.SetPopupOptions(Value: TPopupOptions);
  9958. begin
  9959.   FPopupOptions.Assign(Value);
  9960.   if (Self.FPlotMenu <> nil) then
  9961.     TPlotMenu(FPlotMenu).ApplyOptions(Value);
  9962.   if (Self.FPlotToolBar <> nil) then
  9963.     TPlotToolBar(FPlotToolBar).ApplyOptions(Value);
  9964. end;
  9965.  
  9966. {------------------------------------------------------------------------------
  9967.     Procedure: TCustomPlot.SetPlotMenu
  9968.   Description: standard property Set procedure
  9969.        Author: Mat Ballard
  9970.  Date created: 09/25/2000
  9971. Date modified: 09/25/2000 by Mat Ballard
  9972.       Purpose: sets the PlotMenu property
  9973.  Known Issues:
  9974.  ------------------------------------------------------------------------------}
  9975. procedure TCustomPlot.SetPlotMenu(Value: TMainMenu);
  9976. begin
  9977.   FPlotMenu := Value;
  9978.   if (FPlotMenu <> nil) then
  9979.     TPlotMenu(FPlotMenu).ApplyOptions(FPopupOptions);
  9980. end;
  9981.  
  9982. {------------------------------------------------------------------------------
  9983.     Procedure: TCustomPlot.SetPlotToolBar
  9984.   Description: standard property Set procedure
  9985.        Author: Mat Ballard
  9986.  Date created: 09/25/2000
  9987. Date modified: 04/25/2001 by Mat Ballard
  9988.       Purpose: sets the PlotToolBar property
  9989.  Known Issues:
  9990.  ------------------------------------------------------------------------------}
  9991. procedure TCustomPlot.SetPlotToolBar(Value: TToolBar);
  9992. begin
  9993.   FPlotToolBar := Value;
  9994.   if (FPlotToolBar <> nil) then
  9995.     TPlotToolBar(FPlotToolBar).ApplyOptions(FPopupOptions);
  9996. end;
  9997.  
  9998. {------------------------------------------------------------------------------
  9999.     Procedure: TCustomPlot.SetPlotActionList
  10000.   Description: standard property Set procedure
  10001.        Author: Mat Ballard
  10002.  Date created: 09/25/2000
  10003. Date modified: 09/25/2000 by Mat Ballard
  10004.       Purpose: sets the PlotActionList property
  10005.  Known Issues:
  10006.  ------------------------------------------------------------------------------}
  10007. {$IFDEF DELPHI4_UP}
  10008. {procedure TCustomPlot.SetPlotActionList(Value: TActionList);
  10009. begin
  10010.   FPlotActionList := Value;
  10011. end;}
  10012. {$ENDIF}
  10013.  
  10014. {------------------------------------------------------------------------------
  10015.     Procedure: TCustomPlot.Clear
  10016.   Description: Saves any changed files (at user request) and then clears the SeriesList.
  10017.        Author: Mat Ballard
  10018.  Date created: 04/25/2000
  10019. Date modified: 04/25/2000 by Mat Ballard
  10020.       Purpose: Series management: wraps TSeriesList.ClearSeries
  10021.  Known Issues: it is a fairly brutal way of setting the number of Y Axes
  10022.  ------------------------------------------------------------------------------}
  10023. procedure TCustomPlot.Clear(Cancellable: Boolean);
  10024. var
  10025.   TheResult: Integer;
  10026.   TheMessage: String;
  10027. {$IFDEF MSWINDOWS}
  10028.   pMessage: array[0..255] of Char;
  10029. {$ENDIF}
  10030. begin
  10031.   if (csDesigning in ComponentState) then exit;
  10032.  
  10033.   if (FSeriesList.Count > 0) then
  10034.   begin
  10035.     if (FSeriesList.DataChanged) then
  10036.     begin
  10037.       if (Length(FFileName) > 0) then
  10038.         TheMessage := ExtractFileName(FFileName)
  10039.        else
  10040.         TheMessage := sThisFile;
  10041.        TheMessage := sSaveClick1 + ' ' + TheMessage + ' ' + sBeforeClose;
  10042. {NB: MessageDlg provokes an access violation because the Window may have gone:}
  10043. {$IFDEF MSWINDOWS}
  10044.       StrPCopy(pMessage, TheMessage);
  10045.       if (Cancellable) then
  10046.         TheResult := {Windows.}MessageBox(0, pMessage, pChar(sFileHasChanged), MB_YESNOCANCEL + MB_ICONQUESTION)
  10047.        else
  10048.         TheResult := {Windows.}MessageBox(0, pMessage, pChar(sFileHasChanged), MB_YESNO + MB_ICONQUESTION);
  10049. {$ENDIF}
  10050. {$IFDEF LINUX}
  10051.       if (Cancellable) then
  10052.         TheResult := MessageDlg(sSaveFile,
  10053.           TheMessage,
  10054.           mtWarning,
  10055.           [mbYes, mbNo, mbCancel],
  10056.           0)
  10057.        else
  10058.         TheResult := MessageDlg(sSaveFile,
  10059.           TheMessage,
  10060.           mtWarning,
  10061.           [mbYes, mbNo],
  10062.           0);
  10063. {$ENDIF}
  10064.       case TheResult of
  10065.         mrYes: SaveClick(Self);
  10066.         mrNo: ;
  10067.         mrCancel: Exit;
  10068.       end;
  10069.     end;
  10070.  
  10071.     FSeriesList.ClearSeries;
  10072.     if ((FPlotMenu <> nil) and (Length(FFileName) > 0)) then
  10073.       TPlotMenu(FPlotMenu).AddHistory(FFileName);
  10074.     DoFileClose(FFileName);
  10075.   end;
  10076.   FFileName := '';
  10077. end;
  10078.  
  10079. {------------------------------------------------------------------------------
  10080.     Procedure: TCustomPlot.DoStyleChange
  10081.   Description: informs the user of a change in the plot that requires a repaint
  10082.        Author: Mat Ballard
  10083.  Date created: 02/20/2001
  10084. Date modified: 02/20/2001 by Mat Ballard
  10085.       Purpose: Fires the OnStyleChange event
  10086.  Known Issues:
  10087.  ------------------------------------------------------------------------------}
  10088. procedure TCustomPlot.DoStyleChange(Sender: TObject);
  10089. begin
  10090.   if (IgnoreChanges) then exit;
  10091.  
  10092.   SetAxisDimensions;
  10093.  
  10094.   if assigned(FOnStyleChange) then OnStyleChange(Sender);
  10095.   Refresh;
  10096. end;
  10097.  
  10098. {------------------------------------------------------------------------------
  10099.     Procedure: TCustomPlot.DoDataChange
  10100.   Description: informs the user of a change in the data of the plot that requires a repaint
  10101.        Author: Mat Ballard
  10102.  Date created: 03/07/2001
  10103. Date modified: 03/07/2001 by Mat Ballard
  10104.       Purpose: Fires the OnDataChange event
  10105.  Known Issues:
  10106.  ------------------------------------------------------------------------------}
  10107. procedure TCustomPlot.DoDataChange(Sender: TObject);
  10108. begin
  10109.   if (IgnoreChanges) then exit;
  10110.  
  10111.   if assigned(FOnDataChange) then OnDataChange(Sender);
  10112.   Refresh;
  10113. end;
  10114.  
  10115. {------------------------------------------------------------------------------
  10116.     Procedure: TCustomPlot.DoFileClose
  10117.   Description: informs the user of a file close
  10118.        Author: Mat Ballard
  10119.  Date created: 09/07/2000
  10120. Date modified: 09/07/2000 by Mat Ballard
  10121.       Purpose: Fires the OnFileClose event
  10122.  Known Issues:
  10123.  ------------------------------------------------------------------------------}
  10124. procedure TCustomPlot.DoFileClose(AFileName: String);
  10125. begin
  10126.   if assigned(FOnFileClose) then
  10127.     OnFileClose(Self, AFileName);
  10128. end;
  10129.  
  10130. {------------------------------------------------------------------------------
  10131.      Function: TCustomPlot.GetPlotTypeAsString
  10132.   Description: standard property getting method
  10133.        Author: Mat Ballard
  10134.  Date created: 23/07/2001
  10135. Date modified: 023/07/2001 by Mat Ballard
  10136.       Purpose: gets the PlotType as a string (for BCB users mainly)
  10137.  Known Issues:
  10138.  ------------------------------------------------------------------------------}
  10139. function TCustomPlot.GetPlotTypeAsString: String;
  10140. begin
  10141.   Result := Copy(TypInfo.GetEnumName(TypeInfo(TPlotType), Ord(FPlotType)), 3, 99);
  10142. end;
  10143.  
  10144. {------------------------------------------------------------------------------
  10145.      Function: TCustomPlot.GetZAngle
  10146.   Description: standard property getting method
  10147.        Author: Mat Ballard
  10148.  Date created: 01/07/2001
  10149. Date modified: 01/07/2001 by Mat Ballard
  10150.       Purpose: gets the angle of the Z Axis, if any
  10151.  Known Issues:
  10152.  ------------------------------------------------------------------------------}
  10153. function TCustomPlot.GetZAngle: Word;
  10154. begin
  10155.   if (FZAxis <> nil) then
  10156.     GetZAngle := FZAxis.Angle
  10157.    else
  10158.     GetZAngle := 225;
  10159. end;
  10160.  
  10161. {------------------------------------------------------------------------------
  10162.      Function: TCustomPlot.GetZLength
  10163.   Description: standard property getting method
  10164.        Author: Mat Ballard
  10165.  Date created: 01/07/2001
  10166. Date modified: 01/07/2001 by Mat Ballard
  10167.       Purpose: gets the Length of the Z Axis, if any
  10168.  Known Issues:
  10169.  ------------------------------------------------------------------------------}
  10170. function TCustomPlot.GetZLength: Word;
  10171. begin
  10172.   if (FZAxis <> nil) then
  10173.     GetZLength := FZAxis.Length
  10174.    else
  10175.     GetZLength := 100;
  10176. end;
  10177.  
  10178. {------------------------------------------------------------------------------
  10179.     Procedure: TCustomPlot.SetZAngle
  10180.   Description: standard property setting method
  10181.        Author: Mat Ballard
  10182.  Date created: 01/07/2001
  10183. Date modified: 01/07/2001 by Mat Ballard
  10184.       Purpose: sets the angle of the Z Axis, if any
  10185.  Known Issues:
  10186.  ------------------------------------------------------------------------------}
  10187. procedure TCustomPlot.SetZAngle(Value: Word);
  10188. begin
  10189.   if (FZAxis <> nil) then
  10190.     if (Value <> FZAxis.Angle) then
  10191.       FZAxis.Angle := Value;
  10192. end;
  10193.  
  10194. {------------------------------------------------------------------------------
  10195.     Procedure: TCustomPlot.SetZLength
  10196.   Description: standard property setting method
  10197.        Author: Mat Ballard
  10198.  Date created: 01/07/2001
  10199. Date modified: 01/07/2001 by Mat Ballard
  10200.       Purpose: sets the Length of the Z Axis, if any
  10201.  Known Issues:
  10202.  ------------------------------------------------------------------------------}
  10203. procedure TCustomPlot.SetZLength(Value: Word);
  10204. begin
  10205.   if (FZAxis <> nil) then
  10206.     if (Value <> FZAxis.Length) then
  10207.       FZAxis.Length := Value;
  10208. end;
  10209.  
  10210. {------------------------------------------------------------------------------
  10211.     Procedure: TCustomPlot.SetZLink
  10212.   Description: standard property setting method
  10213.        Author: Mat Ballard
  10214.  Date created: 01/07/2001
  10215. Date modified: 01/07/2001 by Mat Ballard
  10216.       Purpose: sets the Link property - that is, should we link 3D series ?
  10217.  Known Issues:
  10218.  ------------------------------------------------------------------------------}
  10219. procedure TCustomPlot.SetZLink(Value: Boolean);
  10220. begin
  10221.   if (Value <> FZLink) then
  10222.     FZLink := Value;
  10223.   DoStyleChange(Self);
  10224. end;
  10225.  
  10226.  
  10227. {------------------------------------------------------------------------------
  10228.     Procedure: TCustomPlot.SetXYFastAt
  10229.   Description: standard property setting method
  10230.        Author: Mat Ballard
  10231.  Date created: 05/07/2001
  10232. Date modified: 05/07/2001 by Mat Ballard
  10233.       Purpose: sets the Bridge point of the data - when it switches to the
  10234.                hyperfast draw algorithm
  10235.  Known Issues:
  10236.  ------------------------------------------------------------------------------}
  10237. procedure TCustomPlot.SetXYFastAt(Value: Longint);
  10238. begin
  10239.   if (Value > 100) then
  10240.     FXYFastAt := Value;
  10241.   DoStyleChange(Self);
  10242. end;
  10243.  
  10244.  
  10245. end.
  10246.  
  10247.  
  10248.  
  10249.