initial commit
3ce1ca4cba5b4c4d052adb7b436988ee66f18f3a
0 files changed
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..84d8640
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,506 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+
+
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f0c5060
--- /dev/null
+++ b/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Resources;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTrademark( "" )]
+[assembly: AssemblyCulture( "" )]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible( false )]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid( "a552bf32-72a3-4d27-968c-72e7a90243f2" )]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+//[assembly: AllowPartiallyTrustedCallers ]
+
diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..627693e
--- /dev/null
+++ b/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace ZedGraph.Properties {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ZedGraph.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Properties/Resources.resx b/Properties/Resources.resx
new file mode 100644
index 0000000..4fdb1b6
--- /dev/null
+++ b/Properties/Resources.resx
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 1.3
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">1.3</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1">this is my long string</data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ [base64 mime encoded serialized .NET Framework object]
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ [base64 mime encoded string representing a byte array form of the .NET Framework object]
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>1.3</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
\ No newline at end of file
diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..84c5d21
--- /dev/null
+++ b/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace ZedGraph.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Properties/Settings.settings b/Properties/Settings.settings
new file mode 100644
index 0000000..049245f
--- /dev/null
+++ b/Properties/Settings.settings
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+</SettingsFile>
diff --git a/ZedGraph.csproj b/ZedGraph.csproj
new file mode 100644
index 0000000..802d65c
--- /dev/null
+++ b/ZedGraph.csproj
@@ -0,0 +1,46 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0-windows</TargetFramework>
+ <Nullable>enable</Nullable>
+ <UseWindowsForms>true</UseWindowsForms>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
+ <AssemblyVersion>6.0.0.0</AssemblyVersion>
+ <FileVersion>6.0.0.0</FileVersion>
+ <SignAssembly>True</SignAssembly>
+ <AssemblyOriginatorKeyFile>zedgraphkey.snk</AssemblyOriginatorKeyFile>
+ <Title>ZedGraph Library</Title>
+ <Description>ZedGraph Library</Description>
+ <Copyright>Copyright © 2003-2007 John Champion</Copyright>
+ <RunAnalyzersDuringLiveAnalysis>False</RunAnalyzersDuringLiveAnalysis>
+ <RunAnalyzersDuringBuild>False</RunAnalyzersDuringBuild>
+ <EnableNETAnalyzers>False</EnableNETAnalyzers>
+ <NeutralLanguage>en</NeutralLanguage>
+ <Version>$(VersionPrefix)6.0.0</Version>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <DebugType>embedded</DebugType>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Update="Properties\Settings.Designer.cs">
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ </Compile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <None Update="LICENSE.txt">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ </None>
+ <None Update="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+
+</Project>
diff --git a/ZedGraph/ArrowObj.cs b/ZedGraph/ArrowObj.cs
new file mode 100644
index 0000000..5acf3f2
--- /dev/null
+++ b/ZedGraph/ArrowObj.cs
@@ -0,0 +1,322 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents a graphic arrow or line object on the graph. A list of
+ /// ArrowObj objects is maintained by the <see cref="GraphObjList"/> collection class.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-01-25 07:56:08 $ </version>
+ [Serializable]
+ public class ArrowObj : LineObj, ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores the arrowhead size, measured in points.
+ /// Use the public property <see cref="Size"/> to access this value.
+ /// </summary>
+ private float _size;
+ /// <summary>
+ /// Private boolean field that stores the arrowhead state.
+ /// Use the public property <see cref="IsArrowHead"/> to access this value.
+ /// </summary>
+ /// <value> true if an arrowhead is to be drawn, false otherwise </value>
+ private bool _isArrowHead;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ArrowObj"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ /// <summary>
+ /// The default size for the <see cref="ArrowObj"/> item arrowhead
+ /// (<see cref="ArrowObj.Size"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float Size = 12.0F;
+ /// <summary>
+ /// The default display mode for the <see cref="ArrowObj"/> item arrowhead
+ /// (<see cref="ArrowObj.IsArrowHead"/> property). true to show the
+ /// arrowhead, false to hide it.
+ /// </summary>
+ public static bool IsArrowHead = true;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// The size of the arrowhead.
+ /// </summary>
+ /// <remarks>The display of the arrowhead can be
+ /// enabled or disabled with the <see cref="IsArrowHead"/> property.
+ /// </remarks>
+ /// <value> The size is defined in points (1/72 inch) </value>
+ /// <seealso cref="Default.Size"/>
+ public float Size
+ {
+ get { return _size; }
+ set { _size = value; }
+ }
+ /// <summary>
+ /// Determines whether or not to draw an arrowhead
+ /// </summary>
+ /// <value> true to show the arrowhead, false to show the line segment
+ /// only</value>
+ /// <seealso cref="Default.IsArrowHead"/>
+ public bool IsArrowHead
+ {
+ get { return _isArrowHead; }
+ set { _isArrowHead = value; }
+ }
+ #endregion
+
+ #region Constructors
+ /// <overloads>Constructors for the <see cref="ArrowObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the position, color, and size of the
+ /// <see cref="ArrowObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="color">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the arrow</param>
+ /// <param name="size">The size of the arrowhead, measured in points.</param>
+ /// <param name="x1">The x position of the starting point that defines the
+ /// arrow. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y1">The y position of the starting point that defines the
+ /// arrow. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="x2">The x position of the ending point that defines the
+ /// arrow. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y2">The y position of the ending point that defines the
+ /// arrow. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ public ArrowObj( Color color, float size, double x1, double y1,
+ double x2, double y2 )
+ : base( color, x1, y1, x2, y2 )
+ {
+ _isArrowHead = Default.IsArrowHead;
+ _size = size;
+ }
+
+ /// <summary>
+ /// A constructor that allows only the position of the
+ /// arrow to be pre-specified. All other properties are set to
+ /// default values
+ /// </summary>
+ /// <param name="x1">The x position of the starting point that defines the
+ /// <see cref="ArrowObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y1">The y position of the starting point that defines the
+ /// <see cref="ArrowObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="x2">The x position of the ending point that defines the
+ /// <see cref="ArrowObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y2">The y position of the ending point that defines the
+ /// <see cref="ArrowObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ public ArrowObj( double x1, double y1, double x2, double y2 )
+ : this( LineBase.Default.Color, Default.Size, x1, y1, x2, y2 )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor -- places the <see cref="ArrowObj"/> at location
+ /// (0,0) to (1,1). All other values are defaulted.
+ /// </summary>
+ public ArrowObj()
+ :
+ this( LineBase.Default.Color, Default.Size, 0, 0, 1, 1 )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ArrowObj"/> object from which to copy</param>
+ public ArrowObj( ArrowObj rhs )
+ : base( rhs )
+ {
+ _size = rhs.Size;
+ _isArrowHead = rhs.IsArrowHead;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new ArrowObj Clone()
+ {
+ return new ArrowObj( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected ArrowObj( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+
+ _size = info.GetSingle( "size" );
+ _isArrowHead = info.GetBoolean( "isArrowHead" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema3", schema2 );
+ info.AddValue( "size", _size );
+ info.AddValue( "isArrowHead", _isArrowHead );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this object to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ // Convert the arrow coordinates from the user coordinate system
+ // to the screen coordinate system
+ PointF pix1 = this.Location.TransformTopLeft( pane );
+ PointF pix2 = this.Location.TransformBottomRight( pane );
+
+ if ( pix1.X > -10000 && pix1.X < 100000 && pix1.Y > -100000 && pix1.Y < 100000 &&
+ pix2.X > -10000 && pix2.X < 100000 && pix2.Y > -100000 && pix2.Y < 100000 )
+ {
+ // get a scaled size for the arrowhead
+ float scaledSize = (float)( _size * scaleFactor );
+
+ // calculate the length and the angle of the arrow "vector"
+ double dy = pix2.Y - pix1.Y;
+ double dx = pix2.X - pix1.X;
+ float angle = (float)Math.Atan2( dy, dx ) * 180.0F / (float)Math.PI;
+ float length = (float)Math.Sqrt( dx * dx + dy * dy );
+
+ // Save the old transform matrix
+ Matrix transform = g.Transform;
+ // Move the coordinate system so it is located at the starting point
+ // of this arrow
+ g.TranslateTransform( pix1.X, pix1.Y );
+ // Rotate the coordinate system according to the angle of this arrow
+ // about the starting point
+ g.RotateTransform( angle );
+
+ // get a pen according to this arrow properties
+ using ( Pen pen = _line.GetPen( pane, scaleFactor ) )
+ //new Pen( _color, pane.ScaledPenWidth( _penWidth, scaleFactor ) ) )
+ {
+ //pen.DashStyle = _style;
+
+ // Only show the arrowhead if required
+ if ( _isArrowHead )
+ {
+ // Draw the line segment for this arrow
+ g.DrawLine( pen, 0, 0, length - scaledSize + 1, 0 );
+
+ // Create a polygon representing the arrowhead based on the scaled
+ // size
+ PointF[] polyPt = new PointF[4];
+ float hsize = scaledSize / 3.0F;
+ polyPt[0].X = length;
+ polyPt[0].Y = 0;
+ polyPt[1].X = length - scaledSize;
+ polyPt[1].Y = hsize;
+ polyPt[2].X = length - scaledSize;
+ polyPt[2].Y = -hsize;
+ polyPt[3] = polyPt[0];
+
+ using ( SolidBrush brush = new SolidBrush( _line._color ) )
+ // render the arrowhead
+ g.FillPolygon( brush, polyPt );
+ }
+ else
+ g.DrawLine( pen, 0, 0, length, 0 );
+ }
+
+ // Restore the transform matrix back to its original state
+ g.Transform = transform;
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Axis.cs b/ZedGraph/Axis.cs
new file mode 100644
index 0000000..37f5131
--- /dev/null
+++ b/ZedGraph/Axis.cs
@@ -0,0 +1,1447 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The Axis class is an abstract base class that encompasses all properties
+ /// and methods required to define a graph Axis.
+ /// </summary>
+ /// <remarks>This class is inherited by the
+ /// <see cref="XAxis"/>, <see cref="YAxis"/>, and <see cref="Y2Axis"/> classes
+ /// to define specific characteristics for those types.
+ /// </remarks>
+ ///
+ /// <author> John Champion modified by Jerry Vos </author>
+ /// <version> $Revision: 3.76 $ $Date: 2008-02-16 23:21:48 $ </version>
+ [Serializable]
+ abstract public class Axis : ISerializable, ICloneable
+ {
+
+ #region Class Fields
+
+ /// <summary>
+ /// private field that stores the <see cref="ZedGraph.Scale" /> class, which implements all the
+ /// calculations and methods associated with the numeric scale for this
+ /// <see cref="Axis" />. See the public property <see cref="Scale" /> to access this class.
+ /// </summary>
+ internal Scale _scale;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.MinorTic" /> class, which handles all
+ /// the minor tic information. See the public property <see cref="MinorTic" /> to access this class.
+ /// </summary>
+ internal MinorTic _minorTic;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.MajorTic" /> class, which handles all
+ /// the major tic information. See the public property <see cref="MajorTic" /> to access this class.
+ /// </summary>
+ internal MajorTic _majorTic;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.MajorGrid" /> class, which handles all
+ /// the major grid information. See the public property <see cref="MajorGrid" /> to access this class.
+ /// </summary>
+ internal MajorGrid _majorGrid;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.MinorGrid" /> class, which handles all
+ /// the minor grid information. See the public property <see cref="MinorGrid" /> to access this class.
+ /// </summary>
+ internal MinorGrid _minorGrid;
+
+ /// <summary> Private fields for the <see cref="Axis"/> scale rendering properties.
+ /// Use the public properties <see cref="Cross"/> and <see cref="ZedGraph.Scale.BaseTic"/>
+ /// for access to these values.
+ /// </summary>
+ internal double _cross;
+
+ /// <summary> Private field for the <see cref="Axis"/> automatic cross position mode.
+ /// Use the public property <see cref="CrossAuto"/> for access to this value.
+ /// </summary>
+ internal bool _crossAuto;
+
+ /// <summary> Private fields for the <see cref="Axis"/> attributes.
+ /// Use the public properties <see cref="IsVisible"/>, <see cref="IsAxisSegmentVisible"/>
+ /// for access to these values.
+ /// </summary>
+ protected bool _isVisible,
+ _isAxisSegmentVisible;
+
+ /// <summary> Private field for the <see cref="Axis"/> title string.
+ /// Use the public property <see cref="Title"/> for access to this value.
+ /// </summary>
+ protected AxisLabel _title;
+
+ /// <summary>
+ /// A tag object for use by the user. This can be used to store additional
+ /// information associated with the <see cref="Axis"/>. ZedGraph does
+ /// not use this value for any purpose.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if you are going to Serialize ZedGraph data, then any type
+ /// that you store in <see cref="Tag"/> must be a serializable type (or
+ /// it will cause an exception).
+ /// </remarks>
+ public object Tag;
+
+ /// <summary> Private field for the <see cref="Axis"/> drawing dimensions.
+ /// Use the public property <see cref="AxisGap"/>
+ /// for access to these values. </summary>
+ private float _axisGap;
+
+ /// <summary>
+ /// Private field for the <see cref="Axis"/> minimum allowable space allocation.
+ /// Use the public property <see cref="MinSpace"/> to access this value.
+ /// </summary>
+ /// <seealso cref="Default.MinSpace"/>
+ private float _minSpace;
+
+ /// <summary> Private fields for the <see cref="Axis"/> colors.
+ /// Use the public property <see cref="Color"/> for access to this values.
+ /// </summary>
+ private Color _color;
+
+ /// <summary>
+ /// Temporary values for axis space calculations (see <see cref="CalcSpace" />).
+ /// </summary>
+ internal float _tmpSpace;
+
+ #endregion
+
+ #region Events
+
+ /// <summary>
+ /// A delegate that allows full custom formatting of the Axis labels
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> for which the label is to be
+ /// formatted</param>
+ /// <param name="axis">The <see cref="Scale" /> of interest.</param>
+ /// <param name="val">The value to be formatted</param>
+ /// <param name="index">The zero-based index of the label to be formatted</param>
+ /// <returns>
+ /// A string value representing the label, or null if the ZedGraph should go ahead
+ /// and generate the label according to the current settings</returns>
+ /// <seealso cref="ScaleFormatEvent" />
+ public delegate string ScaleFormatHandler( GraphPane pane, Axis axis, double val, int index );
+
+ /// <summary>
+ /// Subscribe to this event to handle custom formatting of the scale labels.
+ /// </summary>
+ public event ScaleFormatHandler ScaleFormatEvent;
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Allow customization of title based on user preferences.
+ /// </summary>
+ /// <param name="axis">The <see cref="Axis" /> of interest.</param>
+ /// <returns>
+ /// A string value representing the label, or null if the ZedGraph should go ahead
+ /// and generate the label according to the current settings. To make the title
+ /// blank, return "".</returns>
+ /// <seealso cref="ScaleFormatEvent" />
+ public delegate string ScaleTitleEventHandler( Axis axis );
+
+ //Revision: JCarpenter 10/06
+ /// <summary>
+ /// Allow customization of the title when the scale is very large
+ /// Subscribe to this event to handle custom formatting of the scale axis label.
+ /// </summary>
+ public event ScaleTitleEventHandler ScaleTitleEvent;
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Axis"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default size for the gap between multiple axes
+ /// (<see cref="Axis.AxisGap"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float AxisGap = 5;
+
+ /// <summary>
+ /// The default setting for the gap between the scale labels and the axis title.
+ /// </summary>
+ public static float TitleGap = 0.0f;
+
+ /// <summary>
+ /// The default font family for the <see cref="Axis"/> <see cref="Title" /> text
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="FontSpec.Family"/> property).
+ /// </summary>
+ public static string TitleFontFamily = "Arial";
+ /// <summary>
+ /// The default font size for the <see cref="Axis"/> <see cref="Title" /> text
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="FontSpec.Size"/> property). Units are
+ /// in points (1/72 inch).
+ /// </summary>
+ public static float TitleFontSize = 14;
+ /// <summary>
+ /// The default font color for the <see cref="Axis"/> <see cref="Title" /> text
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="FontSpec.FontColor"/> property).
+ /// </summary>
+ public static Color TitleFontColor = Color.Black;
+ /// <summary>
+ /// The default font bold mode for the <see cref="Axis"/> <see cref="Title" /> text
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="FontSpec.IsBold"/> property). true
+ /// for a bold typeface, false otherwise.
+ /// </summary>
+ public static bool TitleFontBold = true;
+ /// <summary>
+ /// The default font italic mode for the <see cref="Axis"/> <see cref="Title" /> text
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="FontSpec.IsItalic"/> property). true
+ /// for an italic typeface, false otherwise.
+ /// </summary>
+ public static bool TitleFontItalic = false;
+ /// <summary>
+ /// The default font underline mode for the <see cref="Axis"/> <see cref="Title" /> text
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="FontSpec.IsUnderline"/> property). true
+ /// for an underlined typeface, false otherwise.
+ /// </summary>
+ public static bool TitleFontUnderline = false;
+ /// <summary>
+ /// The default color for filling in the <see cref="Title" /> text background
+ /// (see <see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color TitleFillColor = Color.White;
+ /// <summary>
+ /// The default custom brush for filling in the <see cref="Title" /> text background
+ /// (see <see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush TitleFillBrush = null;
+ /// <summary>
+ /// The default fill mode for filling in the <see cref="Title" /> text background
+ /// (see <see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType TitleFillType = FillType.None;
+
+ /// <summary>
+ /// The default color for the <see cref="Axis"/> itself
+ /// (<see cref="Axis.Color"/> property). This color only affects the
+ /// the axis border.
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default value for <see cref="Axis.IsAxisSegmentVisible"/>, which determines
+ /// whether or not the scale segment itself is visible
+ /// </summary>
+ public static bool IsAxisSegmentVisible = true;
+
+ /// <summary>
+ /// The default setting for the <see cref="Axis"/> scale axis type
+ /// (<see cref="Axis.Type"/> property). This value is set as per
+ /// the <see cref="AxisType"/> enumeration
+ /// </summary>
+ public static AxisType Type = AxisType.Linear;
+
+ /// <summary>
+ /// The default color for the axis segment.
+ /// </summary>
+ public static Color Color = Color.Black;
+
+ /// <summary>
+ /// The default setting for the axis space allocation. This term, expressed in
+ /// points (1/72 inch) and scaled according to <see cref="PaneBase.CalcScaleFactor"/> for the
+ /// <see cref="GraphPane"/>, determines the minimum amount of space an axis must
+ /// have between the <see cref="Chart.Rect"/> and the
+ /// <see cref="PaneBase.Rect"/>. This minimum space
+ /// applies whether <see cref="Axis.IsVisible"/> is true or false.
+ /// </summary>
+ public static float MinSpace = 0f;
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for <see cref="Axis"/> that sets all axis properties
+ /// to default values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public Axis()
+ {
+ _scale = new LinearScale( this );
+
+ _cross = 0.0;
+
+ _crossAuto = true;
+
+ _majorTic = new MajorTic();
+ _minorTic = new MinorTic();
+
+ _majorGrid = new MajorGrid();
+ _minorGrid = new MinorGrid();
+
+ _axisGap = Default.AxisGap;
+
+ _minSpace = Default.MinSpace;
+ _isVisible = true;
+
+ _isAxisSegmentVisible = Default.IsAxisSegmentVisible;
+
+ _title = new AxisLabel( "", Default.TitleFontFamily, Default.TitleFontSize,
+ Default.TitleFontColor, Default.TitleFontBold,
+ Default.TitleFontUnderline, Default.TitleFontItalic );
+ _title.FontSpec.Fill = new Fill( Default.TitleFillColor, Default.TitleFillBrush,
+ Default.TitleFillType );
+
+ _title.FontSpec.Border.IsVisible = false;
+
+
+ _color = Default.Color;
+
+ }
+
+ /// <summary>
+ /// Constructor for <see cref="Axis"/> that sets all axis properties
+ /// to default values as defined in the <see cref="Default"/> class,
+ /// except for the <see cref="Title"/>.
+ /// </summary>
+ /// <param name="title">A string containing the axis title</param>
+ public Axis( string title )
+ : this()
+ {
+ _title._text = title;
+ }
+
+ /// <summary>
+ /// The Copy Constructor.
+ /// </summary>
+ /// <param name="rhs">The Axis object from which to copy</param>
+ public Axis( Axis rhs )
+ {
+ _scale = rhs._scale.Clone( this );
+
+ _cross = rhs._cross;
+
+ _crossAuto = rhs._crossAuto;
+
+ _majorTic = rhs.MajorTic.Clone();
+ _minorTic = rhs.MinorTic.Clone();
+
+ _majorGrid = rhs._majorGrid.Clone();
+ _minorGrid = rhs._minorGrid.Clone();
+
+ _isVisible = rhs.IsVisible;
+
+ _isAxisSegmentVisible = rhs._isAxisSegmentVisible;
+
+ _title = (AxisLabel) rhs.Title.Clone();
+
+ _axisGap = rhs._axisGap;
+
+ _minSpace = rhs.MinSpace;
+
+ _color = rhs.Color;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of Clone.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method must be called with an explicit cast to ICloneable, and
+ /// that it is inherently virtual. For example:
+ /// <code>
+ /// ParentClass foo = new ChildClass();
+ /// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
+ /// </code>
+ /// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
+ /// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
+ /// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
+ /// </remarks>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
+ //return new PaneBase( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Axis( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _cross = info.GetDouble( "cross" );
+ _crossAuto = info.GetBoolean( "crossAuto" );
+
+ _majorTic = (MajorTic)info.GetValue( "MajorTic", typeof( MajorTic ) );
+ _minorTic = (MinorTic)info.GetValue( "MinorTic", typeof( MinorTic ) );
+ _majorGrid = (MajorGrid)info.GetValue( "majorGrid", typeof( MajorGrid ) );
+ _minorGrid = (MinorGrid)info.GetValue( "minorGrid", typeof( MinorGrid ) );
+
+ _isVisible = info.GetBoolean( "isVisible" );
+
+ _title = (AxisLabel) info.GetValue( "title", typeof( AxisLabel ) );
+
+ _minSpace = info.GetSingle( "minSpace" );
+
+ _color = (Color)info.GetValue( "color", typeof( Color ) );
+
+ _isAxisSegmentVisible = info.GetBoolean( "isAxisSegmentVisible" );
+
+
+ _axisGap = info.GetSingle( "axisGap" );
+
+ _scale = (Scale)info.GetValue( "scale", typeof( Scale ) );
+ _scale._ownerAxis = this;
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "cross", _cross );
+ info.AddValue( "crossAuto", _crossAuto );
+
+ info.AddValue( "MajorTic", MajorTic );
+ info.AddValue( "MinorTic", MinorTic );
+ info.AddValue( "majorGrid", _majorGrid );
+ info.AddValue( "minorGrid", _minorGrid );
+
+ info.AddValue( "isVisible", _isVisible );
+
+ info.AddValue( "title", _title );
+
+ info.AddValue( "minSpace", _minSpace );
+
+ info.AddValue( "color", _color );
+
+ info.AddValue( "isAxisSegmentVisible", _isAxisSegmentVisible );
+
+ info.AddValue( "axisGap", _axisGap );
+
+ info.AddValue( "scale", _scale );
+
+ }
+
+ #endregion
+
+ #region Scale Properties
+
+ /// <summary>
+ /// Gets the <see cref="Scale" /> instance associated with this <see cref="Axis" />.
+ /// </summary>
+ public Scale Scale
+ {
+ get { return _scale; }
+ }
+ /// <summary>
+ /// Gets or sets the scale value at which this axis should cross the "other" axis.
+ /// </summary>
+ /// <remarks>This property allows the axis to be shifted away from its default location.
+ /// For example, for a graph with an X range from -100 to +100, the Y Axis can be located
+ /// at the X=0 value rather than the left edge of the ChartRect. This value can be set
+ /// automatically based on the state of <see cref="CrossAuto"/>. If
+ /// this value is set manually, then <see cref="CrossAuto"/> will
+ /// also be set to false. The "other" axis is the axis the handles the second dimension
+ /// for the graph. For the XAxis, the "other" axis is the YAxis. For the YAxis or
+ /// Y2Axis, the "other" axis is the XAxis.
+ /// </remarks>
+ /// <value> The value is defined in user scale units </value>
+ /// <seealso cref="ZedGraph.Scale.Min"/>
+ /// <seealso cref="ZedGraph.Scale.Max"/>
+ /// <seealso cref="ZedGraph.Scale.MajorStep"/>
+ /// <seealso cref="CrossAuto"/>
+ public double Cross
+ {
+ get { return _cross; }
+ set { _cross = value; _crossAuto = false; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the <see cref="Cross"/> value
+ /// is set automatically.
+ /// </summary>
+ /// <value>Set to true to have ZedGraph put the axis in the default location, or false
+ /// to specify the axis location manually with a <see cref="Cross"/> value.</value>
+ /// <seealso cref="ZedGraph.Scale.Min"/>
+ /// <seealso cref="ZedGraph.Scale.Max"/>
+ /// <seealso cref="ZedGraph.Scale.MajorStep"/>
+ /// <seealso cref="Cross"/>
+ public bool CrossAuto
+ {
+ get { return _crossAuto; }
+ set { _crossAuto = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the minimum axis space allocation.
+ /// </summary>
+ /// <remarks>
+ /// This term, expressed in
+ /// points (1/72 inch) and scaled according to <see cref="PaneBase.CalcScaleFactor"/>
+ /// for the <see cref="GraphPane"/>, determines the minimum amount of space
+ /// an axis must have between the <see cref="Chart.Rect">Chart.Rect</see> and the
+ /// <see cref="PaneBase.Rect">GraphPane.Rect</see>. This minimum space
+ /// applies whether <see cref="IsVisible"/> is true or false.
+ /// </remarks>
+ public float MinSpace
+ {
+ get { return _minSpace; }
+ set { _minSpace = value; }
+ }
+
+ #endregion
+
+ #region Tic Properties
+
+ /// <summary>
+ /// The color to use for drawing this <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>
+ /// This affects only the axis segment (see <see cref="IsAxisSegmentVisible" />),
+ /// since the <see cref="Title"/>,
+ /// <see cref="Scale"/>, <see cref="MajorTic" />, <see cref="MinorTic" />,
+ /// <see cref="MajorGrid" />, and <see cref="MinorGrid" />
+ /// all have their own color specification.
+ /// </remarks>
+ /// <value> The color is defined using the
+ /// <see cref="System.Drawing.Color"/> class</value>
+ /// <seealso cref="Default.Color"/>.
+ /// <seealso cref="IsVisible"/>
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; }
+ }
+
+ /// <summary>
+ /// Gets a reference to the <see cref="ZedGraph.MajorTic" /> class instance
+ /// for this <see cref="Axis" />. This class stores all the major tic settings.
+ /// </summary>
+ public MajorTic MajorTic
+ {
+ get { return _majorTic; }
+ }
+ /// <summary>
+ /// Gets a reference to the <see cref="ZedGraph.MinorTic" /> class instance
+ /// for this <see cref="Axis" />. This class stores all the minor tic settings.
+ /// </summary>
+ public MinorTic MinorTic
+ {
+ get { return _minorTic; }
+ }
+
+ #endregion
+
+ #region Grid Properties
+
+ /// <summary>
+ /// Gets a reference to the <see cref="MajorGrid" /> class that contains the properties
+ /// of the major grid.
+ /// </summary>
+ public MajorGrid MajorGrid
+ {
+ get { return _majorGrid; }
+ }
+
+ /// <summary>
+ /// Gets a reference to the <see cref="MinorGrid" /> class that contains the properties
+ /// of the minor grid.
+ /// </summary>
+ public MinorGrid MinorGrid
+ {
+ get { return _minorGrid; }
+ }
+
+
+ #endregion
+
+ #region Type Properties
+
+ /// <summary>
+ /// This property determines whether or not the <see cref="Axis"/> is shown.
+ /// </summary>
+ /// <remarks>
+ /// Note that even if
+ /// the axis is not visible, it can still be actively used to draw curves on a
+ /// graph, it will just be invisible to the user
+ /// </remarks>
+ /// <value>true to show the axis, false to disable all drawing of this axis</value>
+ /// <seealso cref="ZedGraph.Scale.IsVisible"/>.
+ /// <seealso cref="XAxis.Default.IsVisible"/>.
+ /// <seealso cref="YAxis.Default.IsVisible"/>.
+ /// <seealso cref="Y2Axis.Default.IsVisible"/>.
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines whether or not the axis segment (the line that
+ /// represents the axis itself) is drawn.
+ /// </summary>
+ /// <remarks>
+ /// Under normal circumstances, this value won't affect the appearance of the display because
+ /// the Axis segment is overlain by the Axis border (see <see cref="Chart.Border"/>).
+ /// However, when the border is not visible, or when <see cref="Axis.CrossAuto"/> is set to
+ /// false, this value will make a difference.
+ /// </remarks>
+ public bool IsAxisSegmentVisible
+ {
+ get { return _isAxisSegmentVisible; }
+ set { _isAxisSegmentVisible = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="AxisType"/> for this <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>
+ /// The type can be either <see cref="AxisType.Linear"/>,
+ /// <see cref="AxisType.Log"/>, <see cref="AxisType.Date"/>,
+ /// or <see cref="AxisType.Text"/>.
+ /// </remarks>
+ /// <seealso cref="ZedGraph.Scale.IsLog"/>
+ /// <seealso cref="ZedGraph.Scale.IsText"/>
+ /// <seealso cref="ZedGraph.Scale.IsOrdinal"/>
+ /// <seealso cref="ZedGraph.Scale.IsDate"/>
+ /// <seealso cref="ZedGraph.Scale.IsReverse"/>
+ public AxisType Type
+ {
+ get { return _scale.Type; }
+ set { _scale = Scale.MakeNewScale( _scale, value ); }
+ }
+
+ #endregion
+
+ #region Label Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="Label" /> class that contains the title of this
+ /// <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>The title normally shows the basis and dimensions of
+ /// the scale range, such as "Time (Years)". The title is only shown if the
+ /// <see cref="Label.IsVisible"/> property is set to true. If the Title text is empty,
+ /// then no title is shown, and no space is "reserved" for the title on the graph.
+ /// </remarks>
+ /// <value>the title is a string value</value>
+ /// <seealso cref="AxisLabel.IsOmitMag"/>
+ public AxisLabel Title
+ {
+ get { return _title; }
+ set { _title = value; }
+ }
+
+ /// <summary>
+ /// The size of the gap between multiple axes (see <see cref="GraphPane.YAxisList" /> and
+ /// <see cref="GraphPane.Y2AxisList" />).
+ /// </summary>
+ /// <remarks>
+ /// This size will be scaled
+ /// according to the <see cref="PaneBase.CalcScaleFactor"/> for the
+ /// <see cref="GraphPane"/>
+ /// </remarks>
+ /// <value>The axis gap is measured in points (1/72 inch)</value>
+ /// <seealso cref="Default.AxisGap"/>.
+ public float AxisGap
+ {
+ get { return _axisGap; }
+ set { _axisGap = value; }
+ }
+
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Restore the scale ranging to automatic mode, and recalculate the
+ /// <see cref="Axis"/> scale ranges
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <seealso cref="ZedGraph.Scale.MinAuto"/>
+ /// <seealso cref="ZedGraph.Scale.MaxAuto"/>
+ /// <seealso cref="ZedGraph.Scale.MajorStepAuto"/>
+ /// <seealso cref="ZedGraph.Scale.MagAuto"/>
+ /// <seealso cref="ZedGraph.Scale.FormatAuto"/>
+ public void ResetAutoScale( GraphPane pane, Graphics g )
+ {
+ _scale._minAuto = true;
+ _scale._maxAuto = true;
+ _scale._majorStepAuto = true;
+ _scale._minorStepAuto = true;
+ _crossAuto = true;
+ _scale._magAuto = true;
+ //this.numDecAuto = true;
+ _scale._formatAuto = true;
+ pane.AxisChange( g );
+ }
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="Axis"/> to the specified
+ /// <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only
+ /// called by the Draw method of the parent <see cref="GraphPane"/> object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="shiftPos">
+ /// The number of pixels to shift to account for non-primary axis position (e.g.,
+ /// the second, third, fourth, etc. <see cref="YAxis" /> or <see cref="Y2Axis" />.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, float scaleFactor, float shiftPos )
+ {
+ Matrix saveMatrix = g.Transform;
+
+ _scale.SetupScaleData( pane, this );
+
+ if ( _isVisible )
+ {
+ SetTransformMatrix( g, pane, scaleFactor );
+
+ shiftPos = CalcTotalShift( pane, scaleFactor, shiftPos );
+
+ _scale.Draw( g, pane, scaleFactor, shiftPos );
+
+ //DrawTitle( g, pane, scaleFactor );
+
+ g.Transform = saveMatrix;
+ }
+ }
+
+ internal void DrawGrid( Graphics g, GraphPane pane, float scaleFactor, float shiftPos )
+ {
+ if ( _isVisible )
+ {
+ Matrix saveMatrix = g.Transform;
+ SetTransformMatrix( g, pane, scaleFactor );
+
+ double baseVal = _scale.CalcBaseTic();
+ float topPix, rightPix;
+ _scale.GetTopRightPix( pane, out topPix, out rightPix );
+
+ shiftPos = CalcTotalShift( pane, scaleFactor, shiftPos );
+
+ _scale.DrawGrid( g, pane, baseVal, topPix, scaleFactor );
+
+ DrawMinorTics( g, pane, baseVal, shiftPos, scaleFactor, topPix );
+
+ g.Transform = saveMatrix;
+ }
+ }
+
+ /// <summary>
+ /// This method will set the <see cref="MinSpace"/> property for this <see cref="Axis"/>
+ /// using the currently required space multiplied by a fraction (<paramref>bufferFraction</paramref>).
+ /// </summary>
+ /// <remarks>
+ /// The currently required space is calculated using <see cref="CalcSpace"/>, and is
+ /// based on current data ranges, font sizes, etc. The "space" is actually the amount of space
+ /// required to fit the tic marks, scale labels, and axis title.
+ /// </remarks>
+ /// <param name="g">A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.</param>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.</param>
+ /// <param name="bufferFraction">The amount of space to allocate for the axis, expressed
+ /// as a fraction of the currently required space. For example, a value of 1.2 would
+ /// allow for 20% extra above the currently required space.</param>
+ /// <param name="isGrowOnly">If true, then this method will only modify the <see cref="MinSpace"/>
+ /// property if the calculated result is more than the current value.</param>
+ public void SetMinSpaceBuffer( Graphics g, GraphPane pane, float bufferFraction,
+ bool isGrowOnly )
+ {
+ // save the original value of minSpace
+ float oldSpace = this.MinSpace;
+ // set minspace to zero, since we don't want it to affect the CalcSpace() result
+ this.MinSpace = 0;
+ // Calculate the space required for the current graph assuming scalefactor = 1.0
+ // and apply the bufferFraction
+ float fixedSpace;
+ float space = this.CalcSpace( g, pane, 1.0F, out fixedSpace ) * bufferFraction;
+ // isGrowOnly indicates the minSpace can grow but not shrink
+ if ( isGrowOnly )
+ space = Math.Max( oldSpace, space );
+ // Set the minSpace
+ this.MinSpace = space;
+ }
+
+ /// <summary>
+ /// Setup the Transform Matrix to handle drawing of this <see cref="Axis"/>
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ abstract public void SetTransformMatrix( Graphics g, GraphPane pane, float scaleFactor );
+
+
+ /// <summary>
+ /// Calculate the "shift" size, in pixels, in order to shift the axis from its default
+ /// location to the value specified by <see cref="Cross"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>The shift amount measured in pixels</returns>
+ abstract internal float CalcCrossShift( GraphPane pane );
+
+ /// <summary>
+ /// Gets the "Cross" axis that corresponds to this axis.
+ /// </summary>
+ /// <remarks>
+ /// The cross axis is the axis which determines the of this Axis when the
+ /// <see cref="Axis.Cross" >Axis.Cross</see> property is used. The
+ /// cross axis for any <see cref="XAxis" /> or <see cref="X2Axis" />
+ /// is always the primary <see cref="YAxis" />, and
+ /// the cross axis for any <see cref="YAxis" /> or <see cref="Y2Axis" /> is
+ /// always the primary <see cref="XAxis" />.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ abstract public Axis GetCrossAxis( GraphPane pane );
+
+// abstract internal float GetMinPix( GraphPane pane );
+
+ //abstract internal float CalcCrossFraction( GraphPane pane );
+
+ /// <summary>
+ /// Returns the linearized actual cross position for this axis, reflecting the settings of
+ /// <see cref="Cross" />, <see cref="CrossAuto" />, and <see cref="ZedGraph.Scale.IsReverse" />.
+ /// </summary>
+ /// <remarks>
+ /// If the value of <see cref="Cross" /> lies outside the axis range, it is
+ /// limited to the axis range.
+ /// </remarks>
+ internal double EffectiveCrossValue( GraphPane pane )
+ {
+ Axis crossAxis = GetCrossAxis( pane );
+
+ if (crossAxis == null)
+ return 0;
+
+ // Use Linearize here instead of _minLinTemp because this method is called
+ // as part of CalcRect() before scale is fully setup
+ double min = crossAxis._scale.Linearize( crossAxis._scale._min );
+ double max = crossAxis._scale.Linearize( crossAxis._scale._max );
+
+ if ( _crossAuto )
+ {
+ if ( crossAxis._scale.IsReverse == ( this is Y2Axis || this is X2Axis ) )
+ return max;
+ else
+ return min;
+ }
+ else if ( _cross < min )
+ return min;
+ else if ( _cross > max )
+ return max;
+ else
+ return _scale.Linearize( _cross );
+ }
+
+ /// <summary>
+ /// Returns true if the axis is shifted at all due to the setting of
+ /// <see cref="Cross" />. This function will always return false if
+ /// <see cref="CrossAuto" /> is true.
+ /// </summary>
+ internal bool IsCrossShifted( GraphPane pane )
+ {
+ if ( _crossAuto )
+ return false;
+ else
+ {
+ Axis crossAxis = GetCrossAxis( pane );
+ if ( ( ( this is XAxis || this is YAxis ) && !crossAxis._scale.IsReverse ) ||
+ ( ( this is X2Axis || this is Y2Axis ) && crossAxis._scale.IsReverse ) )
+ {
+ if ( _cross <= crossAxis._scale._min )
+ return false;
+ }
+ else
+ {
+ if ( _cross >= crossAxis._scale._max )
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Calculates the proportional fraction of the total cross axis width at which
+ /// this axis is located.
+ /// </summary>
+ /// <param name="pane"></param>
+ /// <returns></returns>
+ internal float CalcCrossFraction( GraphPane pane )
+ {
+ // if this axis is not shifted due to the Cross value
+ if ( !this.IsCrossShifted( pane ) )
+ {
+ // if it's the primary axis and the scale labels are on the inside, then we
+ // don't need to save any room for the axis labels (they will be inside the chart rect)
+ if ( IsPrimary( pane ) && _scale._isLabelsInside )
+ return 1.0f;
+ // otherwise, it's a secondary (outboard) axis and we always save room for the axis and labels.
+ else
+ return 0.0f;
+ }
+
+ double effCross = EffectiveCrossValue( pane );
+ Axis crossAxis = GetCrossAxis( pane );
+
+ // Use Linearize here instead of _minLinTemp because this method is called
+ // as part of CalcRect() before scale is fully setup
+ // double max = crossAxis._scale._maxLinTemp;
+ // double min = crossAxis._scale._minLinTemp;
+ double max = crossAxis._scale.Linearize( crossAxis._scale._min );
+ double min = crossAxis._scale.Linearize( crossAxis._scale._max );
+ float frac;
+
+ if ( ( ( this is XAxis || this is YAxis ) && _scale._isLabelsInside == crossAxis._scale.IsReverse ) ||
+ ( ( this is X2Axis || this is Y2Axis ) && _scale._isLabelsInside != crossAxis._scale.IsReverse ) )
+ frac = (float)( ( effCross - min ) / ( max - min ) );
+ else
+ frac = (float)( ( max - effCross ) / ( max - min ) );
+
+ if ( frac < 0.0f )
+ frac = 0.0f;
+ if ( frac > 1.0f )
+ frac = 1.0f;
+
+ return frac;
+ }
+
+ private float CalcTotalShift( GraphPane pane, float scaleFactor, float shiftPos )
+ {
+ if ( !IsPrimary( pane ) )
+ {
+ // if ( CalcCrossFraction( pane ) != 0.0 )
+ if ( IsCrossShifted( pane ) )
+ {
+ shiftPos = 0;
+ }
+ else
+ {
+ // Scaled size (pixels) of a tic
+ float ticSize = _majorTic.ScaledTic( scaleFactor );
+
+ // if the scalelabels are on the inside, shift everything so the axis is drawn,
+ // for example, to the left side of the available space for a YAxis type
+ if ( _scale._isLabelsInside )
+ {
+ shiftPos += _tmpSpace;
+
+ // shift the axis to leave room for the outside tics
+ if ( _majorTic.IsOutside || _majorTic._isCrossOutside ||
+ _minorTic.IsOutside || _minorTic._isCrossOutside )
+ shiftPos -= ticSize;
+ }
+ else
+ {
+ // if it's not the primary axis, add a tic space for the spacing between axes
+ shiftPos += _axisGap * scaleFactor;
+
+ // if it has inside tics, leave another tic space
+ if ( _majorTic.IsInside || _majorTic._isCrossInside ||
+ _minorTic.IsInside || _minorTic._isCrossInside )
+ shiftPos += ticSize;
+ }
+ }
+ }
+
+ // shift is the position of the actual axis line itself
+ // everything else is based on that position.
+ float crossShift = CalcCrossShift( pane );
+ shiftPos += crossShift;
+
+ return shiftPos;
+ }
+
+ /// <summary>
+ /// Calculate the space required (pixels) for this <see cref="Axis"/> object.
+ /// </summary>
+ /// <remarks>
+ /// This is the total space (vertical space for the X axis, horizontal space for
+ /// the Y axes) required to contain the axis. If <see cref="Cross" /> is zero, then
+ /// this space will be the space required between the <see cref="Chart.Rect" /> and
+ /// the <see cref="PaneBase.Rect" />. This method sets the internal values of
+ /// <see cref="_tmpSpace" /> for use by the <see cref="GraphPane.CalcChartRect(Graphics)" />
+ /// method.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="fixedSpace">The amount of space (pixels) at the edge of the ChartRect
+ /// that is always required for this axis, even if the axis is shifted by the
+ /// <see cref="Cross" /> value.</param>
+ /// <returns>Returns the space, in pixels, required for this axis (between the
+ /// rect and ChartRect)</returns>
+ public float CalcSpace( Graphics g, GraphPane pane, float scaleFactor, out float fixedSpace )
+ {
+ //fixedSpace = 0;
+
+ //Typical character height for the scale font
+ float charHeight = _scale._fontSpec.GetHeight( scaleFactor );
+ // Scaled size (pixels) of a tic
+ float ticSize = _majorTic.ScaledTic( scaleFactor );
+ // Scaled size (pixels) of the axis gap
+ float axisGap = _axisGap * scaleFactor;
+ float scaledLabelGap = _scale._labelGap * charHeight;
+ float scaledTitleGap = _title.GetScaledGap( scaleFactor );
+
+ // The minimum amount of space to reserve for the NORMAL position of the axis. This would
+ // be the left side of the chart rect for the Y axis, the right side for the Y2 axis, etc.
+ // This amount of space is based on the need to reserve space for tics, etc., even if the
+ // Axis.Cross property causes the axis to be in a different location.
+ fixedSpace = 0;
+
+ // The actual space needed for this axis (ignoring the setting of Axis.Cross)
+ _tmpSpace = 0;
+
+ // Account for the Axis
+ if ( _isVisible )
+ {
+ bool hasTic = this.MajorTic.IsOutside || this.MajorTic._isCrossOutside ||
+ this.MinorTic.IsOutside || this.MinorTic._isCrossOutside;
+
+ // account for the tic space. Leave the tic space for any type of outside tic (Outside Tic Space)
+ if ( hasTic )
+ _tmpSpace += ticSize;
+
+ // if this is not the primary axis
+ if ( !IsPrimary( pane ) )
+ {
+ // always leave an extra tic space for the space between the multi-axes (Axis Gap)
+ _tmpSpace += axisGap;
+
+ // if it has inside tics, leave another tic space (Inside Tic Space)
+ if ( this.MajorTic._isInside || this.MajorTic._isCrossInside ||
+ this.MinorTic._isInside || this.MinorTic._isCrossInside )
+ _tmpSpace += ticSize;
+ }
+
+ // tic takes up 1x tic
+ // space between tic and scale label is 0.5 tic
+ // scale label is GetScaleMaxSpace()
+ // space between scale label and axis label is 0.5 tic
+
+ // account for the tic labels + 'LabelGap' tic gap between the tic and the label
+ _tmpSpace += _scale.GetScaleMaxSpace( g, pane, scaleFactor, true ).Height +
+ scaledLabelGap;
+
+ string str = MakeTitle();
+
+ // Only add space for the title if there is one
+ // Axis Title gets actual height
+ // if ( str.Length > 0 && _title._isVisible )
+ if ( !string.IsNullOrEmpty( str ) && _title._isVisible )
+ {
+ //tmpSpace += this.TitleFontSpec.BoundingBox( g, str, scaleFactor ).Height;
+ fixedSpace = this.Title.FontSpec.BoundingBox( g, str, scaleFactor ).Height +
+ scaledTitleGap;
+ _tmpSpace += fixedSpace;
+
+ fixedSpace += scaledTitleGap;
+ }
+
+ if ( hasTic )
+ fixedSpace += ticSize;
+ }
+
+ // for the Y axes, make sure that enough space is left to fit the first
+ // and last X axis scale label
+ if ( this.IsPrimary( pane ) && ( (
+ ( this is YAxis && (
+ ( !pane.XAxis._scale._isSkipFirstLabel && !pane.XAxis._scale._isReverse ) ||
+ ( !pane.XAxis._scale._isSkipLastLabel && pane.XAxis._scale._isReverse ) ) ) ||
+ ( this is Y2Axis && (
+ ( !pane.XAxis._scale._isSkipFirstLabel && pane.XAxis._scale._isReverse ) ||
+ ( !pane.XAxis._scale._isSkipLastLabel && !pane.XAxis._scale._isReverse ) ) ) ) &&
+ pane.XAxis.IsVisible && pane.XAxis._scale._isVisible ) )
+ {
+ // half the width of the widest item, plus a gap of 1/2 the charheight
+ float tmp = pane.XAxis._scale.GetScaleMaxSpace( g, pane, scaleFactor, true ).Width / 2.0F;
+ //+ charHeight / 2.0F;
+ //if ( tmp > tmpSpace )
+ // tmpSpace = tmp;
+
+ fixedSpace = Math.Max( tmp, fixedSpace );
+ }
+
+ // Verify that the minSpace property was satisfied
+ _tmpSpace = Math.Max( _tmpSpace, _minSpace * (float)scaleFactor );
+
+ fixedSpace = Math.Max( fixedSpace, _minSpace * (float)scaleFactor );
+
+ return _tmpSpace;
+ }
+
+ /// <summary>
+ /// Determines if this <see cref="Axis" /> object is a "primary" one.
+ /// </summary>
+ /// <remarks>
+ /// The primary axes are the <see cref="XAxis" /> (always), the first
+ /// <see cref="YAxis" /> in the <see cref="GraphPane.YAxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0), and the first
+ /// <see cref="Y2Axis" /> in the <see cref="GraphPane.Y2AxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0). Note that
+ /// <see cref="GraphPane.YAxis" /> and <see cref="GraphPane.Y2Axis" />
+ /// always reference the primary axes.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>true for a primary <see cref="Axis" /> (for the <see cref="XAxis" />,
+ /// this is always true), false otherwise</returns>
+ abstract internal bool IsPrimary( GraphPane pane );
+
+ internal void FixZeroLine( Graphics g, GraphPane pane, float scaleFactor,
+ float left, float right )
+ {
+ // restore the zero line if needed (since the fill tends to cover it up)
+ if ( _isVisible && _majorGrid._isZeroLine &&
+ _scale._min < 0.0 && _scale._max > 0.0 )
+ {
+ float zeroPix = _scale.Transform( 0.0 );
+
+ using ( Pen zeroPen = new Pen( _color,
+ pane.ScaledPenWidth( _majorGrid._penWidth, scaleFactor ) ) )
+ {
+ g.DrawLine( zeroPen, left, zeroPix, right, zeroPix );
+ //zeroPen.Dispose();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Draw the minor tic marks as required for this <see cref="Axis"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="baseVal">
+ /// The scale value for the first major tic position. This is the reference point
+ /// for all other tic marks.
+ /// </param>
+ /// <param name="shift">The number of pixels to shift this axis, based on the
+ /// value of <see cref="Cross"/>. A positive value is into the ChartRect relative to
+ /// the default axis position.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="topPix">
+ /// The pixel location of the far side of the ChartRect from this axis.
+ /// This value is the ChartRect.Height for the XAxis, or the ChartRect.Width
+ /// for the YAxis and Y2Axis.
+ /// </param>
+ public void DrawMinorTics( Graphics g, GraphPane pane, double baseVal, float shift,
+ float scaleFactor, float topPix )
+ {
+ if ( ( this.MinorTic.IsOutside || this.MinorTic.IsOpposite || this.MinorTic.IsInside ||
+ this.MinorTic._isCrossOutside || this.MinorTic._isCrossInside || _minorGrid._isVisible )
+ && _isVisible )
+ {
+ double tMajor = _scale._majorStep * _scale.MajorUnitMultiplier,
+ tMinor = _scale._minorStep * _scale.MinorUnitMultiplier;
+
+ if ( _scale.IsLog || tMinor < tMajor )
+ {
+ float minorScaledTic = this.MinorTic.ScaledTic( scaleFactor );
+
+ // Minor tics start at the minimum value and step all the way thru
+ // the full scale. This means that if the minor step size is not
+ // an even division of the major step size, the minor tics won't
+ // line up with all of the scale labels and major tics.
+ double first = _scale._minLinTemp,
+ last = _scale._maxLinTemp;
+
+ double dVal = first;
+ float pixVal;
+
+ int iTic = _scale.CalcMinorStart( baseVal );
+ int MajorTic = 0;
+ double majorVal = _scale.CalcMajorTicValue( baseVal, MajorTic );
+
+ using ( Pen pen = new Pen( _minorTic._color,
+ pane.ScaledPenWidth( MinorTic._penWidth, scaleFactor ) ) )
+ using ( Pen minorGridPen = _minorGrid.GetPen( pane, scaleFactor ) )
+ {
+
+ // Draw the minor tic marks
+ while ( dVal < last && iTic < 5000 )
+ {
+ // Calculate the scale value for the current tic
+ dVal = _scale.CalcMinorTicValue( baseVal, iTic );
+ // Maintain a value for the current major tic
+ if ( dVal > majorVal )
+ majorVal = _scale.CalcMajorTicValue( baseVal, ++MajorTic );
+
+ // Make sure that the current value does not match up with a major tic
+ if ( ( ( Math.Abs( dVal ) < 1e-20 && Math.Abs( dVal - majorVal ) > 1e-20 ) ||
+ ( Math.Abs( dVal ) > 1e-20 && Math.Abs( ( dVal - majorVal ) / dVal ) > 1e-10 ) ) &&
+ ( dVal >= first && dVal <= last ) )
+ {
+ pixVal = _scale.LocalTransform( dVal );
+
+ _minorGrid.Draw( g, minorGridPen, pixVal, topPix );
+
+ _minorTic.Draw( g, pane, pen, pixVal, topPix, shift, minorScaledTic );
+ }
+
+ iTic++;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Draw the title for this <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>On entry, it is assumed that the
+ /// graphics transform has been configured so that the origin is at the left side
+ /// of this axis, and the axis is aligned along the X coordinate direction.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="shiftPos">The number of pixels to shift this axis, based on the
+ /// value of <see cref="Cross"/>. A positive value is into the ChartRect relative to
+ /// the default axis position.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DrawTitle( Graphics g, GraphPane pane, float shiftPos, float scaleFactor )
+ {
+ string str = MakeTitle();
+
+ // If the Axis is visible, draw the title
+ //if ( _isVisible && _title._isVisible && str.Length > 0 )
+ if ( _isVisible && _title._isVisible && !string.IsNullOrEmpty( str ) )
+ {
+ bool hasTic = ( _scale._isLabelsInside ?
+ ( this.MajorTic.IsInside || this.MajorTic._isCrossInside ||
+ this.MinorTic.IsInside || this.MinorTic._isCrossInside ) :
+ ( this.MajorTic.IsOutside || this.MajorTic._isCrossOutside || this.MinorTic.IsOutside || this.MinorTic._isCrossOutside ) );
+
+ // Calculate the title position in screen coordinates
+ float x = ( _scale._maxPix - _scale._minPix ) / 2;
+
+ float scaledTic = MajorTic.ScaledTic( scaleFactor );
+ float scaledLabelGap = _scale._fontSpec.GetHeight( scaleFactor ) * _scale._labelGap;
+ float scaledTitleGap = _title.GetScaledGap( scaleFactor );
+
+ // The space for the scale labels is only reserved if the axis is not shifted due to the
+ // cross value. Note that this could be a problem if the axis is only shifted slightly,
+ // since the scale value labels may overlap the axis title. However, it's not possible to
+ // calculate that actual shift amount at this point, because the ChartRect rect has not yet been
+ // calculated, and the cross value is determined using a transform of scale values (which
+ // rely on ChartRect).
+
+ float gap = scaledTic * ( hasTic ? 1.0f : 0.0f ) +
+ this.Title.FontSpec.BoundingBox( g, str, scaleFactor ).Height / 2.0F;
+ float y = ( _scale._isVisible ? _scale.GetScaleMaxSpace( g, pane, scaleFactor, true ).Height
+ + scaledLabelGap : 0 );
+
+ if ( _scale._isLabelsInside )
+ y = shiftPos - y - gap;
+ else
+ y = shiftPos + y + gap;
+
+ if ( !_crossAuto && !_title._isTitleAtCross )
+ y = Math.Max( y, gap );
+
+ AlignV alignV = AlignV.Center;
+
+ // Add in the TitleGap space
+ y += scaledTitleGap;
+
+ // Draw the title
+ this.Title.FontSpec.Draw( g, pane, str, x, y,
+ AlignH.Center, alignV, scaleFactor );
+ }
+ }
+
+ private string MakeTitle()
+ {
+ if ( _title._text == null )
+ _title._text = "";
+
+ // Revision: JCarpenter 10/06
+ // Allow customization of the modified title when the scale is very large
+ // The event handler can edit the full label. If the handler returns
+ // null, then the title will be the default.
+ if ( ScaleTitleEvent != null )
+ {
+ string label = ScaleTitleEvent( this );
+ if ( label != null )
+ return label;
+ }
+
+ // If the Mag is non-zero and IsOmitMag == false, and IsLog == false,
+ // then add the mag indicator to the title.
+ if ( _scale._mag != 0 && !_title._isOmitMag && !_scale.IsLog )
+ return _title._text + String.Format( " (10^{0})", _scale._mag );
+ else
+ return _title._text;
+
+ }
+
+ /// <summary>
+ /// Make a value label for the axis at the specified ordinal position.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="ZedGraph.Scale.IsLog"/>,
+ /// <see cref="ZedGraph.Scale.IsText"/>,
+ /// and other axis format settings. It also implements the ScaleFormatEvent such that
+ /// custom labels can be created.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log
+ /// (<see cref="ZedGraph.Scale.IsLog"/>)
+ /// and text (<see cref="ZedGraph.Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ internal string MakeLabelEventWorks( GraphPane pane, int index, double dVal )
+ {
+ // if there is a valid ScaleFormatEvent, then try to use it to create the label
+ // the label will be non-null if it's to be used
+ if ( this.ScaleFormatEvent != null )
+ {
+ string label;
+
+ label = this.ScaleFormatEvent( pane, this, dVal, index );
+ if ( label != null )
+ return label;
+ }
+
+ // second try. If there's no custom ScaleFormatEvent, then just call
+ // _scale.MakeLabel according to the type of scale
+ if ( this.Scale != null )
+ return _scale.MakeLabel( pane, index, dVal );
+ else
+ return "?";
+ }
+
+ #endregion
+
+ }
+}
+
diff --git a/ZedGraph/AxisLabel.cs b/ZedGraph/AxisLabel.cs
new file mode 100644
index 0000000..1bc8b81
--- /dev/null
+++ b/ZedGraph/AxisLabel.cs
@@ -0,0 +1,179 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles the data associated with text title and its associated font
+ /// properties. Inherits from <see cref="Label" />, and adds <see cref="IsOmitMag" />
+ /// and <see cref="IsTitleAtCross" /> properties, which are specifically associated with
+ /// the <see cref="Axis" /> <see cref="Axis.Title" />.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class AxisLabel : GapLabel, ICloneable, ISerializable
+ {
+ internal bool _isOmitMag,
+ _isTitleAtCross;
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to build an <see cref="AxisLabel" /> from the text and the
+ /// associated font properties.
+ /// </summary>
+ /// <param name="text">The <see cref="string" /> representing the text to be
+ /// displayed</param>
+ /// <param name="fontFamily">The <see cref="String" /> font family name</param>
+ /// <param name="fontSize">The size of the font in points and scaled according
+ /// to the <see cref="PaneBase.CalcScaleFactor" /> logic.</param>
+ /// <param name="color">The <see cref="Color" /> instance representing the color
+ /// of the font</param>
+ /// <param name="isBold">true for a bold font face</param>
+ /// <param name="isItalic">true for an italic font face</param>
+ /// <param name="isUnderline">true for an underline font face</param>
+ public AxisLabel( string text, string fontFamily, float fontSize, Color color, bool isBold,
+ bool isItalic, bool isUnderline ) :
+ base( text, fontFamily, fontSize, color, isBold, isItalic, isUnderline )
+ {
+ _isOmitMag = false;
+ _isTitleAtCross = true;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">the <see cref="AxisLabel" /> instance to be copied.</param>
+ public AxisLabel( AxisLabel rhs )
+ : base( rhs )
+ {
+ _isOmitMag = rhs._isOmitMag;
+ _isTitleAtCross = rhs._isTitleAtCross;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new AxisLabel Clone()
+ {
+ return new AxisLabel( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the property that controls whether or not the magnitude factor (power of 10) for
+ /// this scale will be included in the label.
+ /// </summary>
+ /// <remarks>
+ /// For large scale values, a "magnitude" value (power of 10) is automatically
+ /// used for scaling the graph. This magnitude value is automatically appended
+ /// to the end of the Axis <see cref="Axis.Title"/> (e.g., "(10^4)") to indicate
+ /// that a magnitude is in use. This property controls whether or not the
+ /// magnitude is included in the title. Note that it only affects the axis
+ /// title; a magnitude value may still be used even if it is not shown in the title.
+ /// </remarks>
+ /// <value>true to show the magnitude value, false to hide it</value>
+ /// <seealso cref="Axis.Title"/>
+ /// <seealso cref="Scale.Mag"/>
+ /// <seealso cref="Scale.Format"/>
+ public bool IsOmitMag
+ {
+ get { return _isOmitMag; }
+ set { _isOmitMag = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether the Axis title is located at the
+ /// <see cref="Axis.Cross" />
+ /// value or at the normal position (outside the <see cref="Chart.Rect" />).
+ /// </summary>
+ /// <remarks>
+ /// This value only applies if <see cref="Axis.CrossAuto" /> is false.
+ /// </remarks>
+ public bool IsTitleAtCross
+ {
+ get { return _isTitleAtCross; }
+ set { _isTitleAtCross = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected AxisLabel( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch2 = info.GetInt32( "schema3" );
+
+ _isOmitMag = info.GetBoolean( "isOmitMag" );
+ _isTitleAtCross = info.GetBoolean( "isTitleAtCross" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema3", schema2 );
+ info.AddValue( "isOmitMag", _isVisible );
+ info.AddValue( "isTitleAtCross", _isTitleAtCross );
+ }
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/Bar.cs b/ZedGraph/Bar.cs
new file mode 100644
index 0000000..66b9e36
--- /dev/null
+++ b/ZedGraph/Bar.cs
@@ -0,0 +1,522 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class representing all the characteristics of the bar
+ /// segments that make up a curve on the graph.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.30 $ $Date: 2007-11-03 04:41:28 $ </version>
+ [Serializable]
+ public class Bar : ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Bar"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+ /// <summary>
+ /// Private field that stores the <see cref="Border"/> class that defines the
+ /// properties of the border around this <see cref="BarItem"/>. Use the public
+ /// property <see cref="Border"/> to access this value.
+ /// </summary>
+ private Border _border;
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Bar"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default Bar properties
+ /// <summary>
+ /// The default pen width to be used for drawing the border around the bars
+ /// (<see cref="ZedGraph.LineBase.Width"/> property). Units are points.
+ /// </summary>
+ public static float BorderWidth = 1.0F;
+ /// <summary>
+ /// The default fill mode for bars (<see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FillType = FillType.Brush;
+ /// <summary>
+ /// The default border mode for bars (<see cref="ZedGraph.LineBase.IsVisible"/> property).
+ /// true to display frames around bars, false otherwise
+ /// </summary>
+ public static bool IsBorderVisible = true;
+ /// <summary>
+ /// The default color for drawing frames around bars
+ /// (<see cref="ZedGraph.LineBase.Color"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default color for filling in the bars
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.Red;
+ /// <summary>
+ /// The default custom brush for filling in the bars
+ /// (<see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null; //new LinearGradientBrush( new Rectangle(0,0,100,100),
+ // Color.White, Color.Red, 0F );
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default constructor that sets all <see cref="Bar"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public Bar() : this( Color.Empty )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets the
+ /// <see cref="Color"/> as specified, and the remaining
+ /// <see cref="Bar"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// The specified color is only applied to the
+ /// <see cref="ZedGraph.Fill.Color"/>, and the <see cref="ZedGraph.LineBase.Color"/>
+ /// will be defaulted.
+ /// </summary>
+ /// <param name="color">A <see cref="Color"/> value indicating
+ /// the <see cref="ZedGraph.Fill.Color"/>
+ /// of the Bar.
+ /// </param>
+ public Bar( Color color )
+ {
+ _border = new Border( Default.IsBorderVisible, Default.BorderColor, Default.BorderWidth );
+ _fill = new Fill( color.IsEmpty ? Default.FillColor : color,
+ Default.FillBrush, Default.FillType );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The Bar object from which to copy</param>
+ public Bar( Bar rhs )
+ {
+ _border = (Border) rhs.Border.Clone();
+ _fill = (Fill) rhs.Fill.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Bar Clone()
+ {
+ return new Bar( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Bar( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _fill = (Fill) info.GetValue( "fill", typeof(Fill) );
+ _border = (Border) info.GetValue( "border", typeof(Border) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// The <see cref="Border"/> object used to draw the border around the <see cref="Bar"/>.
+ /// </summary>
+ /// <seealso cref="Default.IsBorderVisible"/>
+ /// <seealso cref="Default.BorderWidth"/>
+ /// <seealso cref="Default.BorderColor"/>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Bar"/>.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Draw the <see cref="Bar"/> to the specified <see cref="Graphics"/> device
+ /// at the specified location. This routine draws a single bar.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="left">The x position of the left side of the bar in
+ /// pixel units</param>
+ /// <param name="right">The x position of the right side of the bar in
+ /// pixel units</param>
+ /// <param name="top">The y position of the top of the bar in
+ /// pixel units</param>
+ /// <param name="bottom">The y position of the bottom of the bar in
+ /// pixel units</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <param name="fullFrame">true to draw the bottom portion of the border around the
+ /// bar (this is for legend entries)</param>
+ /// <param name="dataValue">The data value to be used for a value-based
+ /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>,
+ /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param>
+ /// <param name="isSelected">Indicates that the <see cref="Bar" /> should be drawn
+ /// with attributes from the <see cref="Selection" /> class.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, float left, float right, float top,
+ float bottom, float scaleFactor, bool fullFrame, bool isSelected,
+ PointPair dataValue )
+ {
+ // Do a sanity check to make sure the top < bottom. If not, reverse them
+ if ( top > bottom )
+ {
+ float junk = top;
+ top = bottom;
+ bottom = junk;
+ }
+
+ // Do a sanity check to make sure the left < right. If not, reverse them
+ if ( left > right )
+ {
+ float junk = right;
+ right = left;
+ left = junk;
+ }
+
+ if ( top < -10000 )
+ top = -10000;
+ else if ( top > 10000 )
+ top = 10000;
+ if ( left < -10000 )
+ left = -10000;
+ else if ( left > 10000 )
+ left = 10000;
+ if ( right < -10000 )
+ right = -10000;
+ else if ( right > 10000 )
+ right = 10000;
+ if ( bottom < -10000 )
+ bottom = -10000;
+ else if ( bottom > 10000 )
+ bottom = 10000;
+
+ // Make a rectangle for the bar and draw it
+ RectangleF rect = new RectangleF( left, top, right - left, bottom - top );
+
+ Draw( g, pane, rect, scaleFactor, fullFrame, isSelected, dataValue );
+ }
+
+ /// <summary>
+ /// Draw the <see cref="Bar"/> to the specified <see cref="Graphics"/> device
+ /// at the specified location. This routine draws a single bar.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The rectangle (pixels) to contain the bar</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <param name="fullFrame">true to draw the bottom portion of the border around the
+ /// bar (this is for legend entries)</param>
+ /// <param name="dataValue">The data value to be used for a value-based
+ /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>,
+ /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param>
+ /// <param name="isSelected">Indicates that the <see cref="Bar" /> should be drawn
+ /// with attributes from the <see cref="Selection" /> class.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor,
+ bool fullFrame, bool isSelected, PointPair dataValue )
+ {
+ if ( isSelected )
+ {
+ Selection.Fill.Draw( g, rect, dataValue );
+ Selection.Border.Draw( g, pane, scaleFactor, rect );
+ }
+ else
+ {
+ _fill.Draw( g, rect, dataValue );
+ _border.Draw( g, pane, scaleFactor, rect );
+ }
+ }
+
+ /// <summary>
+ /// Draw the this <see cref="Bar"/> to the specified <see cref="Graphics"/>
+ /// device as a bar at each defined point. This method
+ /// is normally only called by the <see cref="BarItem.Draw"/> method of the
+ /// <see cref="BarItem"/> object
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="CurveItem"/> object representing the
+ /// <see cref="Bar"/>'s to be drawn.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="barWidth">
+ /// The width of each bar, in pixels.
+ /// </param>
+ /// <param name="pos">
+ /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.)
+ /// in the cluster of bars.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DrawBars( Graphics g, GraphPane pane, CurveItem curve,
+ Axis baseAxis, Axis valueAxis,
+ float barWidth, int pos, float scaleFactor )
+ {
+ // For non-cluster bar types, the position is always zero since the bars are on top
+ // of eachother
+ BarType barType = pane._barSettings.Type;
+ if ( barType == BarType.Overlay || barType == BarType.Stack || barType == BarType.PercentStack ||
+ barType == BarType.SortedOverlay )
+ pos = 0;
+
+ // Loop over each defined point and draw the corresponding bar
+ for ( int i=0; i<curve.Points.Count; i++ )
+ DrawSingleBar( g, pane, curve, i, pos, baseAxis, valueAxis, barWidth, scaleFactor );
+ }
+
+ /// <summary>
+ /// Draw the specified single bar (an individual "point") of this series to the specified
+ /// <see cref="Graphics"/> device. This method is not as efficient as
+ /// <see cref="DrawBars"/>, which draws the bars for all points. It is intended to be used
+ /// only for <see cref="BarType.SortedOverlay"/>, which requires special handling of each bar.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="CurveItem"/> object representing the
+ /// <see cref="Bar"/>'s to be drawn.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="pos">
+ /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.)
+ /// in the cluster of bars.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based index number for the single bar to be drawn.
+ /// </param>
+ /// <param name="barWidth">
+ /// The width of each bar, in pixels.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DrawSingleBar( Graphics g, GraphPane pane, CurveItem curve,
+ Axis baseAxis, Axis valueAxis,
+ int pos, int index, float barWidth, float scaleFactor )
+ {
+ // Make sure that a bar value exists for the current curve and current ordinal position
+ if ( index >= curve.Points.Count )
+ return;
+
+ // For Overlay and Stack bars, the position is always zero since the bars are on top
+ // of eachother
+ if ( pane._barSettings.Type == BarType.Overlay || pane._barSettings.Type == BarType.Stack ||
+ pane._barSettings.Type == BarType.PercentStack )
+ pos = 0;
+
+ // Draw the specified bar
+ DrawSingleBar( g, pane, curve, index, pos, baseAxis, valueAxis, barWidth, scaleFactor );
+ }
+
+ /// <summary>
+ /// Protected internal routine that draws the specified single bar (an individual "point")
+ /// of this series to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="CurveItem"/> object representing the
+ /// <see cref="Bar"/>'s to be drawn.</param>
+ /// <param name="index">
+ /// The zero-based index number for the single bar to be drawn.
+ /// </param>
+ /// <param name="pos">
+ /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.)
+ /// in the cluster of bars.
+ /// </param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="barWidth">
+ /// The width of each bar, in pixels.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ virtual protected void DrawSingleBar( Graphics g, GraphPane pane,
+ CurveItem curve,
+ int index, int pos, Axis baseAxis, Axis valueAxis,
+ float barWidth, float scaleFactor )
+ {
+ // pixBase = pixel value for the bar center on the base axis
+ // pixHiVal = pixel value for the bar top on the value axis
+ // pixLowVal = pixel value for the bar bottom on the value axis
+ float pixBase, pixHiVal, pixLowVal;
+
+ float clusterWidth = pane.BarSettings.GetClusterWidth();
+ //float barWidth = curve.GetBarWidth( pane );
+ float clusterGap = pane._barSettings.MinClusterGap * barWidth;
+ float barGap = barWidth * pane._barSettings.MinBarGap;
+
+ // curBase = the scale value on the base axis of the current bar
+ // curHiVal = the scale value on the value axis of the current bar
+ // curLowVal = the scale value of the bottom of the bar
+ double curBase, curLowVal, curHiVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ valueHandler.GetValues( curve, index, out curBase, out curLowVal, out curHiVal );
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !curve.Points[index].IsInvalid )
+ {
+ // calculate a pixel value for the top of the bar on value axis
+ pixLowVal = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curLowVal );
+ pixHiVal = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curHiVal );
+ // calculate a pixel value for the center of the bar on the base axis
+ pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curBase );
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - clusterWidth / 2.0F + clusterGap / 2.0F +
+ pos * ( barWidth + barGap );
+
+ // Draw the bar
+ if ( pane._barSettings.Base == BarBase.X )
+ this.Draw( g, pane, pixSide, pixSide + barWidth, pixLowVal,
+ pixHiVal, scaleFactor, true, curve.IsSelected,
+ curve.Points[index] );
+ else
+ this.Draw( g, pane, pixLowVal, pixHiVal, pixSide, pixSide + barWidth,
+ scaleFactor, true, curve.IsSelected,
+ curve.Points[index] );
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/BarItem.cs b/ZedGraph/BarItem.cs
new file mode 100644
index 0000000..fd9b9e2
--- /dev/null
+++ b/ZedGraph/BarItem.cs
@@ -0,0 +1,456 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates a bar type that displays vertical or horizontal bars
+ /// </summary>
+ /// <remarks>
+ /// The orientation of the bars depends on the state of
+ /// <see cref="BarSettings.Base"/>, and the bars can be stacked or
+ /// clustered, depending on the state of <see cref="BarSettings.Type"/>
+ /// </remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.27 $ $Date: 2007-11-03 04:41:28 $ </version>
+ [Serializable]
+ public class BarItem : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="ZedGraph.Bar"/>
+ /// class defined for this <see cref="BarItem"/>. Use the public
+ /// property <see cref="Bar"/> to access this value.
+ /// </summary>
+ protected Bar _bar;
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets a reference to the <see cref="ZedGraph.Bar"/> class defined
+ /// for this <see cref="BarItem"/>.
+ /// </summary>
+ public Bar Bar
+ {
+ get { return _bar; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return this is HiLowBarItem;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return pane._barSettings.Base == BarBase.X || pane._barSettings.Base == BarBase.X2;
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="BarItem"/>, specifying only the legend label for the bar.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ public BarItem( string label ) : base( label )
+ {
+ _bar = new Bar();
+ }
+ /// <summary>
+ /// Create a new <see cref="BarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="ZedGraph.Bar.Fill"/> and <see cref="ZedGraph.Bar.Border"/> properties.
+ /// </param>
+ public BarItem( string label, double[] x, double[] y, Color color )
+ : this( label, new PointPairList( x, y ), color )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="BarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="ZedGraph.Bar.Fill"/> and <see cref="ZedGraph.Bar.Border"/> properties.
+ /// </param>
+ public BarItem( string label, IPointList points, Color color )
+ : base( label, points )
+ {
+ _bar = new Bar( color );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="BarItem"/> object from which to copy</param>
+ public BarItem( BarItem rhs ) : base( rhs )
+ {
+ //bar = new Bar( rhs.Bar );
+ _bar = rhs._bar.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public BarItem Clone()
+ {
+ return new BarItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected BarItem( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _bar = (Bar) info.GetValue( "bar", typeof(Bar) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "bar", _bar );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Do all rendering associated with this <see cref="BarItem"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">The ordinal position of the current <see cref="Bar"/>
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, GraphPane pane, int pos,
+ float scaleFactor )
+ {
+ // Pass the drawing onto the bar class
+ if ( _isVisible )
+ _bar.DrawBars( g, pane, this, BaseAxis( pane ), ValueAxis( pane ),
+ this.GetBarWidth( pane ), pos, scaleFactor );
+ }
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="BarItem"/> at the specified location
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ _bar.Draw( g, pane, rect, scaleFactor, true, false, null );
+ }
+
+ /// <summary>
+ /// Create a <see cref="TextObj" /> for each bar in the <see cref="GraphPane" />.
+ /// </summary>
+ /// <remarks>
+ /// This method will go through the bars, create a label that corresponds to the bar value,
+ /// and place it on the graph depending on user preferences. This works for horizontal or
+ /// vertical bars in clusters or stacks, but only for <see cref="BarItem" /> types. This method
+ /// does not apply to <see cref="ErrorBarItem" /> or <see cref="HiLowBarItem" /> objects.
+ /// Call this method only after calling <see cref="GraphPane.AxisChange()" />.
+ /// </remarks>
+ /// <param name="pane">The GraphPane in which to place the text labels.</param>
+ /// <param name="isBarCenter">true to center the labels inside the bars, false to
+ /// place the labels just above the top of the bar.</param>
+ /// <param name="valueFormat">The double.ToString string format to use for creating
+ /// the labels.
+ /// </param>
+ public static void CreateBarLabels( GraphPane pane, bool isBarCenter, string valueFormat )
+ {
+ CreateBarLabels( pane, isBarCenter, valueFormat, TextObj.Default.FontFamily,
+ TextObj.Default.FontSize, TextObj.Default.FontColor, TextObj.Default.FontBold,
+ TextObj.Default.FontItalic, TextObj.Default.FontUnderline );
+ }
+
+ /// <summary>
+ /// Create a <see cref="TextObj" /> for each bar in the <see cref="GraphPane" />.
+ /// </summary>
+ /// <remarks>
+ /// This method will go through the bars, create a label that corresponds to the bar value,
+ /// and place it on the graph depending on user preferences. This works for horizontal or
+ /// vertical bars in clusters or stacks, but only for <see cref="BarItem" /> types. This method
+ /// does not apply to <see cref="ErrorBarItem" /> or <see cref="HiLowBarItem" /> objects.
+ /// Call this method only after calling <see cref="GraphPane.AxisChange()" />.
+ /// </remarks>
+ /// <param name="pane">The GraphPane in which to place the text labels.</param>
+ /// <param name="isBarCenter">true to center the labels inside the bars, false to
+ /// place the labels just above the top of the bar.</param>
+ /// <param name="valueFormat">The double.ToString string format to use for creating
+ /// the labels.
+ /// </param>
+ /// <param name="fontColor">The color in which to draw the labels</param>
+ /// <param name="fontFamily">The string name of the font family to use for the labels</param>
+ /// <param name="fontSize">The floating point size of the font, in scaled points</param>
+ /// <param name="isBold">true for a bold font type, false otherwise</param>
+ /// <param name="isItalic">true for an italic font type, false otherwise</param>
+ /// <param name="isUnderline">true for an underline font type, false otherwise</param>
+ public static void CreateBarLabels( GraphPane pane, bool isBarCenter, string valueFormat,
+ string fontFamily, float fontSize, Color fontColor, bool isBold, bool isItalic,
+ bool isUnderline )
+ {
+ bool isVertical = pane.BarSettings.Base == BarBase.X;
+
+ // keep a count of the number of BarItems
+ int curveIndex = 0;
+
+ // Get a valuehandler to do some calculations for us
+ ValueHandler valueHandler = new ValueHandler( pane, true );
+
+ // Loop through each curve in the list
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ // work with BarItems only
+ BarItem bar = curve as BarItem;
+ if ( bar != null )
+ {
+ IPointList points = curve.Points;
+
+ // ADD JKB 9/21/07
+ // The labelOffset should depend on whether the curve is YAxis or Y2Axis.
+ // JHC - Generalize to any value axis
+ // Make the gap between the bars and the labels = 1.5% of the axis range
+ float labelOffset;
+
+ Scale scale = curve.ValueAxis( pane ).Scale;
+ labelOffset = (float)( scale._max - scale._min ) * 0.015f;
+
+ // Loop through each point in the BarItem
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ // Get the high, low and base values for the current bar
+ // note that this method will automatically calculate the "effective"
+ // values if the bar is stacked
+ double baseVal, lowVal, hiVal;
+ valueHandler.GetValues( curve, i, out baseVal, out lowVal, out hiVal );
+
+ // Get the value that corresponds to the center of the bar base
+ // This method figures out how the bars are positioned within a cluster
+ float centerVal = (float)valueHandler.BarCenterValue( bar,
+ bar.GetBarWidth( pane ), i, baseVal, curveIndex );
+
+ // Create a text label -- note that we have to go back to the original point
+ // data for this, since hiVal and lowVal could be "effective" values from a bar stack
+ string barLabelText = ( isVertical ? points[i].Y : points[i].X ).ToString( valueFormat );
+
+ // Calculate the position of the label -- this is either the X or the Y coordinate
+ // depending on whether they are horizontal or vertical bars, respectively
+ float position;
+ if ( isBarCenter )
+ position = (float)( hiVal + lowVal ) / 2.0f;
+ else if ( hiVal >= 0 )
+ position = (float)hiVal + labelOffset;
+ else
+ position = (float)hiVal - labelOffset;
+
+ // Create the new TextObj
+ TextObj label;
+ if ( isVertical )
+ label = new TextObj( barLabelText, centerVal, position );
+ else
+ label = new TextObj( barLabelText, position, centerVal );
+
+ label.FontSpec.Family = fontFamily;
+
+ // Configure the TextObj
+
+ // CHANGE JKB 9/21/07
+ // CoordinateFrame should depend on whether curve is YAxis or Y2Axis.
+ label.Location.CoordinateFrame =
+ (isVertical && curve.IsY2Axis) ? CoordType.AxisXY2Scale : CoordType.AxisXYScale;
+
+ label.FontSpec.Size = fontSize;
+ label.FontSpec.FontColor = fontColor;
+ label.FontSpec.IsItalic = isItalic;
+ label.FontSpec.IsBold = isBold;
+ label.FontSpec.IsUnderline = isUnderline;
+
+ label.FontSpec.Angle = isVertical ? 90 : 0;
+ label.Location.AlignH = isBarCenter ? AlignH.Center :
+ ( hiVal >= 0 ? AlignH.Left : AlignH.Right );
+ label.Location.AlignV = AlignV.Center;
+ label.FontSpec.Border.IsVisible = false;
+ label.FontSpec.Fill.IsVisible = false;
+
+ // Add the TextObj to the GraphPane
+ pane.GraphObjList.Add( label );
+ }
+ curveIndex++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ override public bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = string.Empty;
+
+ if ( i < 0 || i >= _points.Count )
+ return false;
+
+ Axis valueAxis = ValueAxis( pane );
+ Axis baseAxis = BaseAxis( pane );
+
+ // pixBase = pixel value for the bar center on the base axis
+ // pixHiVal = pixel value for the bar top on the value axis
+ // pixLowVal = pixel value for the bar bottom on the value axis
+ float pixBase, pixHiVal, pixLowVal;
+
+ float clusterWidth = pane.BarSettings.GetClusterWidth();
+ float barWidth = GetBarWidth( pane );
+ float clusterGap = pane._barSettings.MinClusterGap * barWidth;
+ float barGap = barWidth * pane._barSettings.MinBarGap;
+
+ // curBase = the scale value on the base axis of the current bar
+ // curHiVal = the scale value on the value axis of the current bar
+ // curLowVal = the scale value of the bottom of the bar
+ double curBase, curLowVal, curHiVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ valueHandler.GetValues( this, i, out curBase, out curLowVal, out curHiVal );
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !_points[i].IsInvalid3D )
+ {
+ // calculate a pixel value for the top of the bar on value axis
+ pixLowVal = valueAxis.Scale.Transform( _isOverrideOrdinal, i, curLowVal );
+ pixHiVal = valueAxis.Scale.Transform( _isOverrideOrdinal, i, curHiVal );
+ // calculate a pixel value for the center of the bar on the base axis
+ pixBase = baseAxis.Scale.Transform( _isOverrideOrdinal, i, curBase );
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - clusterWidth / 2.0F + clusterGap / 2.0F +
+ pane.CurveList.GetBarItemPos( pane, this ) * ( barWidth + barGap );
+
+ // Draw the bar
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixSide, pixLowVal,
+ pixSide + barWidth, pixHiVal );
+ else
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixLowVal, pixSide,
+ pixHiVal, pixSide + barWidth );
+
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/BarSettings.cs b/ZedGraph/BarSettings.cs
new file mode 100644
index 0000000..62debbd
--- /dev/null
+++ b/ZedGraph/BarSettings.cs
@@ -0,0 +1,484 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles the global settings for bar charts
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.6 $ $Date: 2007-12-30 23:27:39 $ </version>
+ [Serializable]
+ public class BarSettings : ISerializable
+ {
+ #region Fields
+
+ /// <summary>Private field that determines the size of the gap between bar clusters
+ /// for bar charts. This gap is expressed as a fraction of the bar size (1.0 means
+ /// leave a 1-barwidth gap between clusters).
+ /// Use the public property <see cref="MinClusterGap"/> to access this value. </summary>
+ private float _minClusterGap;
+ /// <summary>Private field that determines the size of the gap between individual bars
+ /// within a bar cluster for bar charts. This gap is expressed as a fraction of the
+ /// bar size (1.0 means leave a 1-barwidth gap between each bar).
+ /// Use the public property <see cref="MinBarGap"/> to access this value. </summary>
+ private float _minBarGap;
+ /// <summary>Private field that determines the base axis from which <see cref="Bar"/>
+ /// graphs will be displayed. The base axis is the axis from which the bars grow with
+ /// increasing value. The value is of the enumeration type <see cref="ZedGraph.BarBase"/>.
+ /// To access this value, use the public property <see cref="Base"/>.
+ /// </summary>
+ /// <seealso cref="Default.Base"/>
+ private BarBase _base;
+ /// <summary>Private field that determines how the <see cref="BarItem"/>
+ /// graphs will be displayed. See the <see cref="ZedGraph.BarType"/> enum
+ /// for the individual types available.
+ /// To access this value, use the public property <see cref="Type"/>.
+ /// </summary>
+ /// <seealso cref="Default.Type"/>
+ private BarType _type;
+ /// <summary>Private field that determines the width of a bar cluster (for bar charts)
+ /// in user scale units. Normally, this value is 1.0 because bar charts are typically
+ /// <see cref="AxisType.Ordinal"/> or <see cref="AxisType.Text"/>, and the bars are
+ /// defined at ordinal values (1.0 scale units apart). For <see cref="AxisType.Linear"/>
+ /// or other scale types, you can use this value to scale the bars to an arbitrary
+ /// user scale. Use the public property <see cref="ClusterScaleWidth"/> to access this
+ /// value. </summary>
+ internal double _clusterScaleWidth;
+
+ /// <summary>
+ /// Private field that determines if the <see cref="ClusterScaleWidth" /> will be
+ /// calculated automatically. Use the public property <see cref="ClusterScaleWidthAuto" />
+ /// to access this value.
+ /// </summary>
+ internal bool _clusterScaleWidthAuto;
+
+ /// <summary>
+ /// private field that stores the owner GraphPane that contains this BarSettings instance.
+ /// </summary>
+ internal GraphPane _ownerPane;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to build a <see cref="BarSettings" /> instance from the defaults.
+ /// </summary>
+ public BarSettings( GraphPane parentPane )
+ {
+ _minClusterGap = Default.MinClusterGap;
+ _minBarGap = Default.MinBarGap;
+ _clusterScaleWidth = Default.ClusterScaleWidth;
+ _clusterScaleWidthAuto = Default.ClusterScaleWidthAuto;
+ _base = Default.Base;
+ _type = Default.Type;
+
+ _ownerPane = parentPane;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">the <see cref="BarSettings" /> instance to be copied.</param>
+ /// <param name="parentPane">The <see cref="GraphPane" /> that will be the
+ /// parent of this new BarSettings object.</param>
+ public BarSettings( BarSettings rhs, GraphPane parentPane )
+ {
+ _minClusterGap = rhs._minClusterGap;
+ _minBarGap = rhs._minBarGap;
+ _clusterScaleWidth = rhs._clusterScaleWidth;
+ _clusterScaleWidthAuto = rhs._clusterScaleWidthAuto;
+ _base = rhs._base;
+ _type = rhs._type;
+
+ _ownerPane = parentPane;
+ }
+
+ #endregion
+
+ #region Bar Properties
+
+ /// <summary>
+ /// The minimum space between <see cref="Bar"/> clusters, expressed as a
+ /// fraction of the bar size.
+ /// </summary>
+ /// <seealso cref="Default.MinClusterGap"/>
+ /// <seealso cref="MinBarGap"/>
+ /// <seealso cref="ClusterScaleWidth"/>
+ public float MinClusterGap
+ {
+ get { return _minClusterGap; }
+ set { _minClusterGap = value; }
+ }
+ /// <summary>
+ /// The minimum space between individual <see cref="Bar">Bars</see>
+ /// within a cluster, expressed as a
+ /// fraction of the bar size.
+ /// </summary>
+ /// <seealso cref="Default.MinBarGap"/>
+ /// <seealso cref="MinClusterGap"/>
+ /// <seealso cref="ClusterScaleWidth"/>
+ public float MinBarGap
+ {
+ get { return _minBarGap; }
+ set { _minBarGap = value; }
+ }
+ /// <summary>Determines the base axis from which <see cref="Bar"/>
+ /// graphs will be displayed.
+ /// </summary>
+ /// <remarks>The base axis is the axis from which the bars grow with
+ /// increasing value. The value is of the enumeration type <see cref="ZedGraph.BarBase"/>.
+ /// </remarks>
+ /// <seealso cref="Default.Base"/>
+ public BarBase Base
+ {
+ get { return _base; }
+ set { _base = value; }
+ }
+ /// <summary>Determines how the <see cref="BarItem"/>
+ /// graphs will be displayed. See the <see cref="ZedGraph.BarType"/> enum
+ /// for the individual types available.
+ /// </summary>
+ /// <seealso cref="Default.Type"/>
+ public BarType Type
+ {
+ get { return _type; }
+ set { _type = value; }
+ }
+ /// <summary>
+ /// The width of an individual bar cluster on a <see cref="Bar"/> graph.
+ /// This value only applies to bar graphs plotted on non-ordinal X axis
+ /// types (<see cref="AxisType.Linear"/>, <see cref="AxisType.Log"/>, and
+ /// <see cref="AxisType.Date"/>.
+ /// </summary>
+ /// <remarks>
+ /// This value can be calculated automatically if <see cref="ClusterScaleWidthAuto" />
+ /// is set to true. In this case, ClusterScaleWidth will be calculated if
+ /// <see cref="Base" /> refers to an <see cref="Axis" /> of a non-ordinal type
+ /// (<see cref="Scale.IsAnyOrdinal" /> is false). The ClusterScaleWidth is calculated
+ /// from the minimum difference found between any two points on the <see cref="Base" />
+ /// <see cref="Axis" /> for any <see cref="BarItem" /> in the
+ /// <see cref="GraphPane.CurveList" />. The ClusterScaleWidth is set automatically
+ /// each time <see cref="GraphPane.AxisChange()" /> is called. Calculations are
+ /// done by the <see cref="BarSettings.CalcClusterScaleWidth" /> method.
+ /// </remarks>
+ /// <seealso cref="Default.ClusterScaleWidth"/>
+ /// <seealso cref="ClusterScaleWidthAuto"/>
+ /// <seealso cref="MinBarGap"/>
+ /// <seealso cref="MinClusterGap"/>
+ public double ClusterScaleWidth
+ {
+ get { return _clusterScaleWidth; }
+ set { _clusterScaleWidth = value; _clusterScaleWidthAuto = false; }
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines if the <see cref="ClusterScaleWidth" /> will be
+ /// calculated automatically.
+ /// </summary>
+ /// <remarks>true for the <see cref="ClusterScaleWidth" /> to be calculated
+ /// automatically based on the available data, false otherwise. This value will
+ /// be set to false automatically if the <see cref="ClusterScaleWidth" /> value
+ /// is changed by the user.
+ /// </remarks>
+ /// <seealso cref="Default.ClusterScaleWidthAuto"/>
+ /// <seealso cref="ClusterScaleWidth"/>
+ public bool ClusterScaleWidthAuto
+ {
+ get { return _clusterScaleWidthAuto; }
+ set { _clusterScaleWidthAuto = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <remarks>
+ /// You MUST set the _ownerPane property after deserializing a BarSettings object.
+ /// </remarks>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the
+ /// serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains
+ /// the serialized data
+ /// </param>
+ internal BarSettings( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _minClusterGap = info.GetSingle( "minClusterGap" );
+ _minBarGap = info.GetSingle( "minBarGap" );
+ _clusterScaleWidth = info.GetDouble( "clusterScaleWidth" );
+ _clusterScaleWidthAuto = info.GetBoolean( "clusterScaleWidthAuto" );
+ _base = (BarBase)info.GetValue( "base", typeof( BarBase ) );
+ _type = (BarType)info.GetValue( "type", typeof( BarType ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "minClusterGap", _minClusterGap );
+ info.AddValue( "minBarGap", _minBarGap );
+ info.AddValue( "clusterScaleWidth", _clusterScaleWidth );
+ info.AddValue( "clusterScaleWidthAuto", _clusterScaleWidthAuto );
+ info.AddValue( "base", _base );
+ info.AddValue( "type", _type );
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Calculate the width of an individual bar cluster on a <see cref="BarItem"/> graph.
+ /// This value only applies to bar graphs plotted on non-ordinal X axis
+ /// types (<see cref="Scale.IsAnyOrdinal" /> is false).
+ /// </summary>
+ /// <remarks>
+ /// This value can be calculated automatically if <see cref="ClusterScaleWidthAuto" />
+ /// is set to true. In this case, ClusterScaleWidth will be calculated if
+ /// <see cref="Base" /> refers to an <see cref="Axis" /> of a non-ordinal type
+ /// (<see cref="Scale.IsAnyOrdinal" /> is false). The ClusterScaleWidth is calculated
+ /// from the minimum difference found between any two points on the <see cref="Base" />
+ /// <see cref="Axis" /> for any <see cref="BarItem" /> in the
+ /// <see cref="GraphPane.CurveList" />. The ClusterScaleWidth is set automatically
+ /// each time <see cref="GraphPane.AxisChange()" /> is called.
+ /// </remarks>
+ /// <seealso cref="Default.ClusterScaleWidth"/>
+ /// <seealso cref="ClusterScaleWidthAuto"/>
+ /// <seealso cref="MinBarGap"/>
+ /// <seealso cref="MinClusterGap"/>
+ public void CalcClusterScaleWidth()
+ {
+ Axis baseAxis = BarBaseAxis();
+
+ // First, calculate the clusterScaleWidth for BarItem objects
+ if ( _clusterScaleWidthAuto && !baseAxis.Scale.IsAnyOrdinal )
+ {
+ double minStep = Double.MaxValue;
+
+ foreach ( CurveItem curve in _ownerPane.CurveList )
+ {
+ IPointList list = curve.Points;
+
+ if ( curve is BarItem )
+ {
+ double step = GetMinStepSize( curve.Points, baseAxis );
+ minStep = step < minStep ? step : minStep;
+ }
+ }
+
+ if ( minStep == Double.MaxValue )
+ minStep = 1.0;
+
+ _clusterScaleWidth = minStep;
+ }
+
+ // Second, calculate the sizes of any HiLowBarItem and JapaneseCandleStickItem objects
+ foreach ( CurveItem curve in _ownerPane.CurveList )
+ {
+ IPointList list = curve.Points;
+
+// if ( curve is HiLowBarItem &&
+// (curve as HiLowBarItem).Bar.IsAutoSize )
+// {
+// ( curve as HiLowBarItem ).Bar._userScaleSize =
+// GetMinStepSize( list, baseAxis );
+// }
+// else if ( curve is JapaneseCandleStickItem &&
+ if ( curve is JapaneseCandleStickItem &&
+ (curve as JapaneseCandleStickItem).Stick.IsAutoSize )
+ {
+ ( curve as JapaneseCandleStickItem ).Stick._userScaleSize =
+ GetMinStepSize( list, baseAxis );
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Determine the minimum increment between individual points to be used for
+ /// calculating a bar size that fits without overlapping
+ /// </summary>
+ /// <param name="list">The <see cref="IPointList" /> list of points for the bar
+ /// of interest</param>
+ /// <param name="baseAxis">The base axis for the bar</param>
+ /// <returns>The minimum increment between bars along the base axis</returns>
+ internal static double GetMinStepSize( IPointList list, Axis baseAxis )
+ {
+ double minStep = Double.MaxValue;
+
+ if ( list.Count <= 0 || baseAxis._scale.IsAnyOrdinal )
+ return 1.0;
+
+ PointPair lastPt = list[0];
+ for ( int i = 1; i < list.Count; i++ )
+ {
+ PointPair pt = list[i];
+ if ( !pt.IsInvalid || !lastPt.IsInvalid )
+ {
+ double step;
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ step = pt.X - lastPt.X;
+ else
+ step = pt.Y - lastPt.Y;
+
+ if ( step > 0 && step < minStep )
+ minStep = step;
+ }
+
+ lastPt = pt;
+ }
+
+ double range = baseAxis.Scale._maxLinearized - baseAxis.Scale._minLinearized;
+ if ( range <= 0 )
+ minStep = 1.0;
+// else if ( minStep <= 0 || minStep < 0.001 * range || minStep > range )
+ else if ( minStep <= 0 || minStep > range )
+ minStep = 0.1 * range;
+
+ return minStep;
+ }
+
+ /// <summary>
+ /// Determine the width, in screen pixel units, of each bar cluster including
+ /// the cluster gaps and bar gaps.
+ /// </summary>
+ /// <remarks>This method calls the <see cref="Scale.GetClusterWidth(GraphPane)"/>
+ /// method for the base <see cref="Axis"/> for <see cref="Bar"/> graphs
+ /// (the base <see cref="Axis"/> is assigned by the <see cref="ZedGraph.BarSettings.Base"/>
+ /// property).
+ /// </remarks>
+ /// <seealso cref="ZedGraph.BarBase"/>
+ /// <seealso cref="ZedGraph.BarSettings"/>
+ /// <seealso cref="Scale.GetClusterWidth(GraphPane)"/>
+ /// <seealso cref="ZedGraph.BarSettings.Type"/>
+ /// <returns>The width of each bar cluster, in pixel units</returns>
+ public float GetClusterWidth()
+ {
+ return BarBaseAxis()._scale.GetClusterWidth( _ownerPane );
+ }
+
+ /// <summary>
+ /// Determine the <see cref="Axis"/> from which the <see cref="Bar"/> charts are based.
+ /// </summary>
+ /// <seealso cref="ZedGraph.BarBase"/>
+ /// <seealso cref="BarSettings"/>
+ /// <seealso cref="ZedGraph.BarSettings.Base"/>
+ /// <seealso cref="Scale.GetClusterWidth(GraphPane)"/>
+ /// <returns>The <see cref="Axis"/> class for the axis from which the bars are based</returns>
+ public Axis BarBaseAxis()
+ {
+ Axis barAxis;
+ if ( _base == BarBase.Y )
+ barAxis = _ownerPane.YAxis;
+ else if ( _base == BarBase.Y2 )
+ barAxis = _ownerPane.Y2Axis;
+ else if ( _base == BarBase.X2 )
+ barAxis = _ownerPane.X2Axis;
+ else
+ barAxis = _ownerPane.XAxis;
+
+ return barAxis;
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="BarSettings"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default dimension gap between clusters of bars on a
+ /// <see cref="Bar"/> graph.
+ /// This dimension is expressed in terms of the normal bar width.
+ /// </summary>
+ /// <seealso cref="Default.MinBarGap"/>
+ /// <seealso cref="BarSettings.MinClusterGap"/>
+ public static float MinClusterGap = 1.0F;
+ /// <summary>
+ /// The default dimension gap between each individual bar within a bar cluster
+ /// on a <see cref="Bar"/> graph.
+ /// This dimension is expressed in terms of the normal bar width.
+ /// </summary>
+ /// <seealso cref="Default.MinClusterGap"/>
+ /// <seealso cref="BarSettings.MinBarGap"/>
+ public static float MinBarGap = 0.2F;
+ /// <summary>The default value for the <see cref="BarSettings.Base"/>, which determines the base
+ /// <see cref="Axis"/> from which the <see cref="Bar"/> graphs will be displayed.
+ /// </summary>
+ /// <seealso cref="BarSettings.Base"/>
+ public static BarBase Base = BarBase.X;
+ /// <summary>The default value for the <see cref="BarSettings.Type"/> property, which
+ /// determines if the bars are drawn overlapping eachother in a "stacked" format,
+ /// or side-by-side in a "cluster" format. See the <see cref="ZedGraph.BarType"/>
+ /// for more information.
+ /// </summary>
+ /// <seealso cref="BarSettings.Type"/>
+ public static BarType Type = BarType.Cluster;
+
+ /// <summary>
+ /// The default width of a bar cluster
+ /// on a <see cref="Bar"/> graph. This value only applies to
+ /// <see cref="Bar"/> graphs, and only when the
+ /// <see cref="Axis.Type"/> is <see cref="AxisType.Linear"/>,
+ /// <see cref="AxisType.Log"/> or <see cref="AxisType.Date"/>.
+ /// This dimension is expressed in terms of X scale user units.
+ /// </summary>
+ /// <seealso cref="Default.MinClusterGap"/>
+ /// <seealso cref="BarSettings.MinBarGap"/>
+ public static double ClusterScaleWidth = 1.0;
+
+ /// <summary>
+ /// The default value for <see cref="BarSettings.ClusterScaleWidthAuto" />.
+ /// </summary>
+ public static bool ClusterScaleWidthAuto = true;
+ }
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/BasicArrayPointList.cs b/ZedGraph/BasicArrayPointList.cs
new file mode 100644
index 0000000..c3adf4a
--- /dev/null
+++ b/ZedGraph/BasicArrayPointList.cs
@@ -0,0 +1,147 @@
+//============================================================================
+//BasicArrayPointList Class
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A data collection class for ZedGraph, provided as an alternative to <see cref="PointPairList" />.
+ /// </summary>
+ /// <remarks>
+ /// The data storage class for ZedGraph can be any type, so long as it uses the <see cref="IPointList" />
+ /// interface. This class, albeit simple, is a demonstration of implementing the <see cref="IPointList" />
+ /// interface to provide a simple data collection using only two arrays. The <see cref="IPointList" />
+ /// interface can also be used as a layer between ZedGraph and a database, for example.
+ /// </remarks>
+ /// <seealso cref="PointPairList" />
+ /// <seealso cref="IPointList" />
+ ///
+ /// <author> John Champion</author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-02-18 05:51:53 $ </version>
+ [Serializable]
+ public class BasicArrayPointList : IPointList
+ {
+ #region Fields
+
+ /// <summary>
+ /// Instance of an array of x values
+ /// </summary>
+ public double[] x;
+ /// <summary>
+ /// Instance of an array of x values
+ /// </summary>
+ public double[] y;
+
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Indexer to access the specified <see cref="PointPair"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <remarks>
+ /// Returns <see cref="PointPairBase.Missing" /> for any value of <see paramref="index" />
+ /// that is outside of its corresponding array bounds.
+ /// </remarks>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="PointPair"/> object to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object reference.</value>
+ public PointPair this[ int index ]
+ {
+ get
+ {
+ double xVal, yVal;
+ if ( index >= 0 && index < x.Length )
+ xVal = x[index];
+ else
+ xVal = PointPair.Missing;
+
+ if ( index >= 0 && index < y.Length )
+ yVal = y[index];
+ else
+ yVal = PointPair.Missing;
+ return new PointPair( xVal, yVal, PointPair.Missing, null );
+ }
+ set
+ {
+ if ( index >= 0 && index < x.Length )
+ x[index] = value.X;
+ if ( index >= 0 && index < y.Length )
+ y[index] = value.Y;
+ }
+ }
+
+ /// <summary>
+ /// Returns the number of points available in the arrays. Count will be the greater
+ /// of the lengths of the X and Y arrays.
+ /// </summary>
+ public int Count
+ {
+ get { return x.Length > y.Length ? x.Length : y.Length; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to initialize the PointPairList from two arrays of
+ /// type double.
+ /// </summary>
+ public BasicArrayPointList( double[] x, double[] y )
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The PointPairList from which to copy</param>
+ public BasicArrayPointList( BasicArrayPointList rhs )
+ {
+ x = (double[]) rhs.x.Clone();
+ y = (double[]) rhs.y.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public BasicArrayPointList Clone()
+ {
+ return new BasicArrayPointList( this );
+ }
+
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Border.cs b/ZedGraph/Border.cs
new file mode 100644
index 0000000..6193e52
--- /dev/null
+++ b/ZedGraph/Border.cs
@@ -0,0 +1,249 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that encapsulates Border (frame) properties for an object. The <see cref="Border"/> class
+ /// is used in a variety of ZedGraph objects to handle the drawing of the Border around the object.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.18 $ $Date: 2007-03-17 18:43:44 $ </version>
+ [Serializable]
+ public class Border : LineBase, ISerializable, ICloneable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores the amount of inflation to be done on the rectangle
+ /// before rendering. This allows the border to be inset or outset relative to
+ /// the actual rectangle area. Use the public property <see cref="InflateFactor"/>
+ /// to access this value.
+ /// </summary>
+ private float _inflateFactor;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Fill"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ /// <summary>
+ /// The default value for <see cref="Border.InflateFactor"/>, in units of points (1/72 inch).
+ /// </summary>
+ /// <seealso cref="Border.InflateFactor"/>
+ public static float InflateFactor = 0.0F;
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// The default constructor. Initialized to default values.
+ /// </summary>
+ public Border() : base()
+ {
+ _inflateFactor = Default.InflateFactor;
+ }
+
+ /// <summary>
+ /// Constructor that specifies the visibility, color and penWidth of the Border.
+ /// </summary>
+ /// <param name="isVisible">Determines whether or not the Border will be drawn.</param>
+ /// <param name="color">The color of the Border</param>
+ /// <param name="width">The width, in points (1/72 inch), for the Border.</param>
+ public Border( bool isVisible, Color color, float width ) :
+ base( color )
+ {
+ _width = width;
+ _isVisible = isVisible;
+ }
+
+ /// <summary>
+ /// Constructor that specifies the color and penWidth of the Border.
+ /// </summary>
+ /// <param name="color">The color of the Border</param>
+ /// <param name="width">The width, in points (1/72 inch), for the Border.</param>
+ public Border( Color color, float width ) :
+ this( !color.IsEmpty, color, width )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The Border object from which to copy</param>
+ public Border( Border rhs ) : base( rhs )
+ {
+ _inflateFactor = rhs._inflateFactor;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Border Clone()
+ {
+ return new Border( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Border( SerializationInfo info, StreamingContext context ) :
+ base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _inflateFactor = info.GetSingle( "inflateFactor" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema", schema );
+ info.AddValue( "inflateFactor", _inflateFactor );
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets or sets the amount of inflation to be done on the rectangle
+ /// before rendering.
+ /// </summary>
+ /// <remarks>This allows the border to be inset or outset relative to
+ /// the actual rectangle area.
+ /// </remarks>
+ public float InflateFactor
+ {
+ get { return _inflateFactor; }
+ set { _inflateFactor = value; }
+ }
+ #endregion
+
+ #region Methods
+ /*
+ /// <summary>
+ /// Create a new <see cref="Pen"/> object from the properties of this
+ /// <see cref="Border"/> object.
+ /// </summary>
+ /// <param name="isPenWidthScaled">
+ /// Set to true to have the <see cref="Border"/> pen width scaled with the
+ /// scaleFactor.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <returns>A <see cref="Pen"/> object with the proper color and pen width.</returns>
+ public Pen MakePen( bool isPenWidthScaled, float scaleFactor )
+ {
+ float scaledPenWidth = _width;
+ if ( isPenWidthScaled )
+ scaledPenWidth = (float)(_width * scaleFactor);
+
+ return new Pen( _color, scaledPenWidth );
+ }
+ */
+
+ /// <summary>
+ /// Draw the specified Border (<see cref="RectangleF"/>) using the properties of
+ /// this <see cref="Border"/> object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <param name="rect">A <see cref="RectangleF"/> struct to be drawn.</param>
+ public void Draw( Graphics g, PaneBase pane, float scaleFactor, RectangleF rect )
+ {
+ // Need to use the RectangleF props since rounding it can cause the axisFrame to
+ // not line up properly with the last tic mark
+ if ( _isVisible )
+ {
+ RectangleF tRect = rect;
+
+ float scaledInflate = (float) ( _inflateFactor * scaleFactor );
+ tRect.Inflate( scaledInflate, scaledInflate );
+
+ using ( Pen pen = GetPen( pane, scaleFactor) )
+ g.DrawRectangle( pen, tRect.X, tRect.Y, tRect.Width, tRect.Height );
+ }
+ }
+
+ #endregion
+ }
+}
+
+
+
+
+
+
+
+
diff --git a/ZedGraph/BoxObj.cs b/ZedGraph/BoxObj.cs
new file mode 100644
index 0000000..9f40d8d
--- /dev/null
+++ b/ZedGraph/BoxObj.cs
@@ -0,0 +1,347 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents a bordered and/or filled box (rectangle) object on
+ /// the graph. A list of
+ /// BoxObj objects is maintained by the <see cref="GraphObjList"/> collection class.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.3 $ $Date: 2007-01-25 07:56:08 $ </version>
+ [Serializable]
+ public class BoxObj : GraphObj, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="BoxObj"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ protected Fill _fill;
+ /// <summary>
+ /// Private field that determines the properties of the border around this
+ /// <see cref="BoxObj"/>
+ /// Use the public property <see cref="Border"/> to access this value.
+ /// </summary>
+ protected Border _border;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ArrowObj"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ /// <summary>
+ /// The default pen width used for the <see cref="BoxObj"/> border
+ /// (<see cref="ZedGraph.LineBase.Width"/> property). Units are points (1/72 inch).
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The default color used for the <see cref="BoxObj"/> border
+ /// (<see cref="ZedGraph.LineBase.Color"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default color used for the <see cref="BoxObj"/> fill
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.White;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="BoxObj"/>.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Border"/> object, which
+ /// determines the properties of the border around this
+ /// <see cref="BoxObj"/>
+ /// </summary>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+ #endregion
+
+ #region Constructors
+ /// <overloads>Constructors for the <see cref="BoxObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the position, border color, and solid fill color
+ /// of the <see cref="BoxObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="borderColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the box border</param>
+ /// <param name="fillColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the box fill (will be a solid color fill)</param>
+ /// <param name="x">The x location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="y">The y location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="width">The width of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="height">The height of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ public BoxObj( double x, double y, double width, double height, Color borderColor, Color fillColor )
+ : base( x, y, width, height )
+ {
+ this.Border = new Border( borderColor, Default.PenWidth );
+ this.Fill = new Fill( fillColor );
+ }
+
+ /// <summary>
+ /// A constructor that allows the position
+ /// of the <see cref="BoxObj"/> to be pre-specified. Other properties are defaulted.
+ /// </summary>
+ /// <param name="x">The x location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="y">The y location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="width">The width of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="height">The height of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ public BoxObj( double x, double y, double width, double height )
+ :
+ base( x, y, width, height )
+ {
+ this.Border = new Border( Default.BorderColor, Default.PenWidth );
+ this.Fill = new Fill( Default.FillColor );
+ }
+
+ /// <summary>
+ /// A default constructor that creates a <see cref="BoxObj"/> using a location of (0,0),
+ /// and a width,height of (1,1). Other properties are defaulted.
+ /// </summary>
+ public BoxObj() : this( 0, 0, 1, 1 )
+ {
+ }
+
+ /// <summary>
+ /// A constructor that allows the position, border color, and two-color
+ /// gradient fill colors
+ /// of the <see cref="BoxObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="borderColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the box border</param>
+ /// <param name="fillColor1">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the start of the box gradient fill</param>
+ /// <param name="fillColor2">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the end of the box gradient fill</param>
+ /// <param name="x">The x location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="y">The y location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="width">The width of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="height">The height of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ public BoxObj( double x, double y, double width, double height, Color borderColor,
+ Color fillColor1, Color fillColor2 ) :
+ base( x, y, width, height )
+ {
+ this.Border = new Border( borderColor, Default.PenWidth );
+ this.Fill = new Fill( fillColor1, fillColor2 );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="BoxObj"/> object from which to copy</param>
+ public BoxObj( BoxObj rhs ) : base( rhs )
+ {
+ this.Border = rhs.Border.Clone();
+ this.Fill = rhs.Fill.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public BoxObj Clone()
+ {
+ return new BoxObj( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected BoxObj( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _fill = (Fill) info.GetValue( "fill", typeof(Fill) );
+ _border = (Border) info.GetValue( "border", typeof(Border) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this object to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ // Convert the arrow coordinates from the user coordinate system
+ // to the screen coordinate system
+ RectangleF pixRect = this.Location.TransformRect( pane );
+
+ // Clip the rect to just outside the PaneRect so we don't end up with wild coordinates.
+ RectangleF tmpRect = pane.Rect;
+ tmpRect.Inflate( 20, 20 );
+ pixRect.Intersect( tmpRect );
+
+ if ( Math.Abs( pixRect.Left ) < 100000 &&
+ Math.Abs( pixRect.Top ) < 100000 &&
+ Math.Abs( pixRect.Right ) < 100000 &&
+ Math.Abs( pixRect.Bottom ) < 100000 )
+ {
+ // If the box is to be filled, fill it
+ _fill.Draw( g, pixRect );
+
+ // Draw the border around the box if required
+ _border.Draw( g, pane, scaleFactor, pixRect );
+ }
+ }
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="BoxObj"/>.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ if ( ! base.PointInBox(pt, pane, g, scaleFactor ) )
+ return false;
+
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ RectangleF pixRect = _location.TransformRect( pane );
+
+ return pixRect.Contains( pt );
+ }
+
+ /// <summary>
+ /// Determines the shape type and Coords values for this GraphObj
+ /// </summary>
+ override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor,
+ out string shape, out string coords )
+ {
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ RectangleF pixRect = _location.TransformRect( pane );
+
+ shape = "rect";
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixRect.Left, pixRect.Top, pixRect.Right, pixRect.Bottom );
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Chart.cs b/ZedGraph/Chart.cs
new file mode 100644
index 0000000..694352b
--- /dev/null
+++ b/ZedGraph/Chart.cs
@@ -0,0 +1,255 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles the properties of the charting area (where the curves are
+ /// actually drawn), which is bounded by the <see cref="XAxis" />, <see cref="YAxis"/>,
+ /// and <see cref="Y2Axis" />.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class Chart : ICloneable, ISerializable
+ {
+ /// <summary>
+ /// The rectangle that contains the area bounded by the axes, in pixel units
+ /// </summary>
+ internal RectangleF _rect;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Chart"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ internal Fill _fill;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Border"/> data for this
+ /// <see cref="Chart"/>. Use the public property <see cref="Border"/> to
+ /// access this value.
+ /// </summary>
+ internal Border _border;
+
+ /// <summary>Private field that determines if the <see cref="Rect"/> will be
+ /// sized automatically. Use the public property <see cref="IsRectAuto"/> to access
+ /// this value. </summary>
+ internal bool _isRectAuto;
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public Chart()
+ {
+ _isRectAuto = true;
+ _border = new Border( Default.IsBorderVisible, Default.BorderColor, Default.BorderPenWidth );
+ _fill = new Fill( Default.FillColor, Default.FillBrush, Default.FillType );
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">The source <see cref="Chart" /> to be copied.</param>
+ public Chart( Chart rhs )
+ {
+ _border = rhs._border.Clone();
+ _fill = rhs._fill.Clone();
+ _rect = rhs._rect;
+ _isRectAuto = rhs._isRectAuto;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Chart Clone()
+ {
+ return new Chart( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the rectangle that contains the area bounded by the axes
+ /// (<see cref="XAxis"/>, <see cref="YAxis"/>, and <see cref="Y2Axis"/>).
+ /// If you set this value manually, then the <see cref="IsRectAuto"/>
+ /// value will automatically be set to false.
+ /// </summary>
+ /// <value>The rectangle units are in screen pixels</value>
+ public RectangleF Rect
+ {
+ get { return _rect; }
+ set { _rect = value; _isRectAuto = false; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Chart"/>.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Border"/> class for drawing the border
+ /// border around the <see cref="Chart"/>
+ /// </summary>
+ /// <seealso cref="Default.BorderColor"/>
+ /// <seealso cref="Default.BorderPenWidth"/>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a boolean value that determines whether or not the
+ /// <see cref="Rect"/> will be calculated automatically (almost always true).
+ /// </summary>
+ /// <remarks>
+ /// If you have a need to set the ChartRect manually, such as you have multiple graphs
+ /// on a page and you want to line up the edges perfectly, you can set this value
+ /// to false. If you set this value to false, you must also manually set
+ /// the <see cref="Rect"/> property.
+ /// You can easily determine the ChartRect that ZedGraph would have
+ /// calculated by calling the <see cref="GraphPane.CalcChartRect(Graphics)"/> method, which returns
+ /// a chart rect sized for the current data range, scale sizes, etc.
+ /// </remarks>
+ /// <value>true to have ZedGraph calculate the ChartRect, false to do it yourself</value>
+ public bool IsRectAuto
+ {
+ get { return _isRectAuto; }
+ set { _isRectAuto = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Chart( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _rect = (RectangleF)info.GetValue( "rect", typeof( RectangleF ) );
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+ _border = (Border)info.GetValue( "border", typeof( Border ) );
+ _isRectAuto = info.GetBoolean( "isRectAuto" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "rect", _rect );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "isRectAuto", _isRectAuto );
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Chart"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default color for the <see cref="Chart"/> border.
+ /// (<see cref="Chart.Border"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default color for the <see cref="Chart"/> background.
+ /// (<see cref="Chart.Fill"/> property).
+ /// </summary>
+ public static Color FillColor = Color.White;
+ /// <summary>
+ /// The default brush for the <see cref="GraphPane.Chart"/> background.
+ /// (<see cref="ZedGraph.Fill.Brush"/> property of <see cref="Chart.Fill"/>).
+ /// </summary>
+ public static Brush FillBrush = null;
+ /// <summary>
+ /// The default <see cref="FillType"/> for the <see cref="GraphPane.Chart"/> background.
+ /// (<see cref="ZedGraph.Fill.Type"/> property of <see cref="Chart.Fill"/>).
+ /// </summary>
+ public static FillType FillType = FillType.Brush;
+ /// <summary>
+ /// The default pen width for drawing the
+ /// <see cref="GraphPane.Chart"/> border
+ /// (<see cref="Chart.Border"/> property).
+ /// Units are in points (1/72 inch).
+ /// </summary>
+ public static float BorderPenWidth = 1F;
+ /// <summary>
+ /// The default display mode for the <see cref="Chart"/> border
+ /// (<see cref="Chart.Border"/> property). true
+ /// to show the border border, false to omit the border
+ /// </summary>
+ public static bool IsBorderVisible = true;
+
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/CollectionPlus.cs b/ZedGraph/CollectionPlus.cs
new file mode 100644
index 0000000..8c7423a
--- /dev/null
+++ b/ZedGraph/CollectionPlus.cs
@@ -0,0 +1,162 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright (C) 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection base class containing basic extra functionality to be inherited
+ /// by <see cref="CurveList"/>, <see cref="IPointList"/>,
+ /// <see cref="GraphObjList"/>.
+ /// </summary>
+ /// <remarks>The methods in this collection operate on basic
+ /// <see cref="object"/> types. Therefore, in order to make sure that
+ /// the derived classes remain strongly-typed, there are no Add() or
+ /// Insert() methods here, and no methods that return an object.
+ /// Only Remove(), Move(), IndexOf(), etc. methods are included.</remarks>
+ ///
+ /// <author> John Champion</author>
+ /// <version> $Revision: 3.8 $ $Date: 2006-06-24 20:26:43 $ </version>
+ [Serializable]
+ public class CollectionPlus : CollectionBase
+ {
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public CollectionPlus() : base()
+ {
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the specified object
+ /// in the collection.
+ /// </summary>
+ /// <param name="item">A reference to the object that is to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified object, or -1 if the
+ /// object is not in the list</returns>
+ /// <seealso cref="IList.IndexOf"/>
+ public int IndexOf( object item )
+ {
+ return List.IndexOf( item );
+ }
+
+ /// <summary>
+ /// Remove an object from the collection at the specified ordinal location.
+ /// </summary>
+ /// <param name="index">
+ /// An ordinal position in the list at which the object to be removed
+ /// is located.
+ /// </param>
+ /// <seealso cref="IList.Remove"/>
+ public void Remove( int index )
+ {
+ if ( index >= 0 && index < List.Count )
+ List.RemoveAt( index );
+ }
+
+ /// <summary>
+ /// Remove an object from the collection based on an object reference.
+ /// </summary>
+ /// <param name="item">A reference to the object that is to be
+ /// removed.</param>
+ /// <seealso cref="IList.Remove"/>
+ public void Remove( object item )
+ {
+ List.Remove( item );
+ }
+
+ /// <summary>
+ /// Move the position of the object at the specified index
+ /// to the new relative position in the list.</summary>
+ /// <remarks>For Graphic type objects, this method controls the
+ /// Z-Order of the items. Objects at the beginning of the list
+ /// appear in front of objects at the end of the list.</remarks>
+ /// <param name="index">The zero-based index of the object
+ /// to be moved.</param>
+ /// <param name="relativePos">The relative number of positions to move
+ /// the object. A value of -1 will move the
+ /// object one position earlier in the list, a value
+ /// of 1 will move it one position later. To move an item to the
+ /// beginning of the list, use a large negative value (such as -999).
+ /// To move it to the end of the list, use a large positive value.
+ /// </param>
+ /// <returns>The new position for the object, or -1 if the object
+ /// was not found.</returns>
+ public int Move( int index, int relativePos )
+ {
+ if ( index < 0 || index >= List.Count )
+ return -1;
+ object obj = List[index];
+ List.RemoveAt( index );
+ index += relativePos;
+ if ( index < 0 )
+ index = 0;
+ if ( index > List.Count )
+ index = List.Count;
+ List.Insert( index, obj );
+ return index;
+ }
+
+ /*
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 1;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected CollectionPlus( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ [SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema", schema );
+ }
+ #endregion
+*/
+ }
+}
diff --git a/ZedGraph/ColorSymbolRotator.cs b/ZedGraph/ColorSymbolRotator.cs
new file mode 100644
index 0000000..fbabb6b
--- /dev/null
+++ b/ZedGraph/ColorSymbolRotator.cs
@@ -0,0 +1,188 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using Color = System.Drawing.Color;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class used to get the next color/symbol for GraphPane.AddCurve methods.
+ /// </summary>
+ ///
+ /// <author> Jerry Vos modified by John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2006-06-24 20:26:43 $ </version>
+ public class ColorSymbolRotator
+ {
+ #region Static fields
+ /// <summary>
+ /// The <see cref="Color"/>s <see cref="ColorSymbolRotator"/>
+ /// rotates through.
+ /// </summary>
+ public static readonly Color[] COLORS = new Color[]
+ {
+ Color.Red,
+ Color.Blue,
+ Color.Green,
+ Color.Purple,
+ Color.Cyan,
+ Color.Pink,
+ Color.LightBlue,
+ Color.PaleVioletRed,
+ Color.SeaGreen,
+ Color.Yellow
+ };
+
+ /// <summary>
+ /// The <see cref="SymbolType"/>s <see cref="ColorSymbolRotator"/>
+ /// rotates through.
+ /// </summary>
+ public static readonly SymbolType[] SYMBOLS = new SymbolType[]
+ {
+ SymbolType.Circle,
+ SymbolType.Diamond,
+ SymbolType.Plus,
+ SymbolType.Square,
+ SymbolType.Star,
+ SymbolType.Triangle,
+ SymbolType.TriangleDown,
+ SymbolType.XCross,
+ SymbolType.HDash,
+ SymbolType.VDash
+ };
+
+ private static ColorSymbolRotator _staticInstance;
+ #endregion
+
+ #region Fields
+ /// <summary>
+ /// The index of the next color to be used. Note: may be
+ /// > COLORS.Length, it is reset to 0 on the next call if it is.
+ /// </summary>
+ protected int colorIndex = 0;
+
+ /// <summary>
+ /// The index of the next symbol to be used. Note: may be
+ /// > SYMBOLS.Length, it is reset to 0 on the next call if it is.
+ /// </summary>
+ protected int symbolIndex = 0;
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Retrieves the next color in the rotation Calling this
+ /// method has the side effect of incrementing the color index.
+ /// <seealso cref="NextSymbol"/>
+ /// <seealso cref="NextColorIndex"/>
+ /// </summary>
+ public Color NextColor
+ {
+ get { return COLORS[NextColorIndex]; }
+ }
+
+ /// <summary>
+ /// Retrieves the index of the next color to be used. Calling this
+ /// method has the side effect of incrementing the color index.
+ /// </summary>
+ public int NextColorIndex
+ {
+ get
+ {
+ if (colorIndex >= COLORS.Length)
+ colorIndex = 0;
+
+ return colorIndex++;
+ }
+ set
+ {
+ colorIndex = value;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves the next color in the rotation. Calling this
+ /// method has the side effect of incrementing the symbol index.
+ /// <seealso cref="NextColor"/>
+ /// <seealso cref="NextSymbolIndex"/>
+ /// </summary>
+ public SymbolType NextSymbol
+ {
+ get { return SYMBOLS[NextSymbolIndex]; }
+ }
+
+ /// <summary>
+ /// Retrieves the index of the next symbol to be used. Calling this
+ /// method has the side effect of incrementing the symbol index.
+ /// </summary>
+ public int NextSymbolIndex
+ {
+ get
+ {
+ if (symbolIndex >= SYMBOLS.Length)
+ symbolIndex = 0;
+
+ return symbolIndex++;
+ }
+ set
+ {
+ symbolIndex = value;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves the <see cref="ColorSymbolRotator"/> instance used by the
+ /// static methods.
+ /// <seealso cref="StaticNextColor"/>
+ /// <seealso cref="StaticNextSymbol"/>
+ /// </summary>
+ public static ColorSymbolRotator StaticInstance
+ {
+ get
+ {
+ if (_staticInstance == null)
+ _staticInstance = new ColorSymbolRotator();
+
+ return _staticInstance;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves the next color from this class's static
+ /// <see cref="ColorSymbolRotator"/> instance
+ /// <seealso cref="StaticInstance"/>
+ /// <seealso cref="StaticNextSymbol"/>
+ /// </summary>
+ public static Color StaticNextColor
+ {
+ get { return StaticInstance.NextColor; }
+ }
+
+ /// <summary>
+ /// Retrieves the next symbol type from this class's static
+ /// <see cref="ColorSymbolRotator"/> instance
+ /// <seealso cref="StaticInstance"/>
+ /// <seealso cref="StaticNextColor"/>
+ /// </summary>
+ public static SymbolType StaticNextSymbol
+ {
+ get { return StaticInstance.NextSymbol; }
+ }
+ #endregion
+ }
+}
diff --git a/ZedGraph/CurveItem.cs b/ZedGraph/CurveItem.cs
new file mode 100644
index 0000000..50789ee
--- /dev/null
+++ b/ZedGraph/CurveItem.cs
@@ -0,0 +1,1228 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#if ( !DOTNET1 ) // Is this a .Net 2 compilation?
+using System.Collections.Generic;
+#endif
+
+namespace ZedGraph
+{
+
+ /// <summary>
+ /// This class contains the data and methods for an individual curve within
+ /// a graph pane. It carries the settings for the curve including the
+ /// key and item names, colors, symbols and sizes, linetypes, etc.
+ /// </summary>
+ ///
+ /// <author> John Champion
+ /// modified by Jerry Vos </author>
+ /// <version> $Revision: 3.43 $ $Date: 2007-11-03 04:41:28 $ </version>
+ [Serializable]
+ abstract public class CurveItem : ISerializable, ICloneable
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// protected field that stores a <see cref="Label" /> instance for this
+ /// <see cref="CurveItem"/>, which is used for the <see cref="Legend" />
+ /// label. Use the public
+ /// property <see cref="Label"/> to access this value.
+ /// </summary>
+ internal Label _label;
+
+ /// <summary>
+ /// protected field that stores the boolean value that determines whether this
+ /// <see cref="CurveItem"/> is on the bottom X axis or the top X axis (X2).
+ /// Use the public property <see cref="IsX2Axis"/> to access this value.
+ /// </summary>
+ protected bool _isX2Axis;
+ /// <summary>
+ /// protected field that stores the boolean value that determines whether this
+ /// <see cref="CurveItem"/> is on the left Y axis or the right Y axis (Y2).
+ /// Use the public property <see cref="IsY2Axis"/> to access this value.
+ /// </summary>
+ protected bool _isY2Axis;
+
+ /// <summary>
+ /// protected field that stores the index number of the Y Axis to which this
+ /// <see cref="CurveItem" /> belongs. Use the public property <see cref="YAxisIndex" />
+ /// to access this value.
+ /// </summary>
+ protected int _yAxisIndex;
+
+ /// <summary>
+ /// protected field that stores the boolean value that determines whether this
+ /// <see cref="CurveItem"/> is visible on the graph.
+ /// Use the public property <see cref="IsVisible"/> to access this value.
+ /// Note that this value turns the curve display on or off, but it does not
+ /// affect the display of the legend entry. To hide the legend entry, you
+ /// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
+ /// </summary>
+ protected bool _isVisible;
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Protected field that stores the boolean value that determines whether this
+ /// <see cref="CurveItem"/> is selected on the graph.
+ /// Use the public property <see cref="IsSelected"/> to access this value.
+ /// Note that this value changes the curve display color, but it does not
+ /// affect the display of the legend entry. To hide the legend entry, you
+ /// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
+ /// </summary>
+ protected bool _isSelected;
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Protected field that stores the boolean value that determines whether this
+ /// <see cref="CurveItem"/> can be selected in the graph.
+ /// </summary>
+ protected bool _isSelectable;
+
+ /// <summary>
+ /// protected field that stores a boolean value which allows you to override the normal
+ /// ordinal axis behavior. Use the public property <see cref="IsOverrideOrdinal"/> to
+ /// access this value.
+ /// </summary>
+ protected bool _isOverrideOrdinal;
+
+ /// <summary>
+ /// The <see cref="IPointList"/> of value sets that
+ /// represent this <see cref="CurveItem"/>.
+ /// The size of this list determines the number of points that are
+ /// plotted. Note that values defined as
+ /// System.Double.MaxValue are considered "missing" values
+ /// (see <see cref="PointPairBase.Missing"/>),
+ /// and are not plotted. The curve will have a break at these points
+ /// to indicate the values are missing.
+ /// </summary>
+ protected IPointList _points;
+
+ /// <summary>
+ /// A tag object for use by the user. This can be used to store additional
+ /// information associated with the <see cref="CurveItem"/>. ZedGraph does
+ /// not use this value for any purpose.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if you are going to Serialize ZedGraph data, then any type
+ /// that you store in <see cref="Tag"/> must be a serializable type (or
+ /// it will cause an exception).
+ /// </remarks>
+ public object Tag;
+
+ /// <summary>
+ /// Protected field that stores the hyperlink information for this object.
+ /// </summary>
+ internal Link _link;
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// <see cref="CurveItem"/> constructor the pre-specifies the curve label, the
+ /// x and y data values as a <see cref="IPointList"/>, the curve
+ /// type (Bar or Line/Symbol), the <see cref="Color"/>, and the
+ /// <see cref="SymbolType"/>. Other properties of the curve are
+ /// defaulted to the values in the <see cref="GraphPane.Default"/> class.
+ /// </summary>
+ /// <param name="label">A string label (legend entry) for this curve</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ public CurveItem( string label, double[] x, double[] y ) :
+ this( label, new PointPairList( x, y ) )
+ {
+ }
+/*
+ public CurveItem( string _label, int y ) : this( _label, new IPointList( ) )
+ {
+ }
+*/
+ /// <summary>
+ /// <see cref="CurveItem"/> constructor the pre-specifies the curve label, the
+ /// x and y data values as a <see cref="IPointList"/>, the curve
+ /// type (Bar or Line/Symbol), the <see cref="Color"/>, and the
+ /// <see cref="SymbolType"/>. Other properties of the curve are
+ /// defaulted to the values in the <see cref="GraphPane.Default"/> class.
+ /// </summary>
+ /// <param name="label">A string label (legend entry) for this curve</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ public CurveItem( string label, IPointList? points )
+ {
+ Init( label );
+
+ if ( points == null )
+ _points = new PointPairList();
+ else
+ //this.points = (IPointList) _points.Clone();
+ _points = points;
+ }
+
+ /// <summary>
+ /// Internal initialization routine thats sets some initial values to defaults.
+ /// </summary>
+ /// <param name="label">A string label (legend entry) for this curve</param>
+ private void Init( string label )
+ {
+ _label = new Label( label, null );
+ _isY2Axis = false;
+ _isX2Axis = false;
+ _isVisible = true;
+ _isOverrideOrdinal = false;
+ this.Tag = null;
+ _yAxisIndex = 0;
+ _link = new Link();
+ }
+
+ /// <summary>
+ /// <see cref="CurveItem"/> constructor that specifies the label of the CurveItem.
+ /// This is the same as <c>CurveItem(label, null, null)</c>.
+ /// <seealso cref="CurveItem( string, double[], double[] )"/>
+ /// </summary>
+ /// <param name="label">A string label (legend entry) for this curve</param>
+ public CurveItem( string label ): this( label, null )
+ {
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public CurveItem( )
+ {
+ Init( null );
+ }
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The CurveItem object from which to copy</param>
+ public CurveItem( CurveItem rhs )
+ {
+ _label = rhs._label.Clone();
+ _isY2Axis = rhs.IsY2Axis;
+ _isX2Axis = rhs.IsX2Axis;
+ _isVisible = rhs.IsVisible;
+ _isOverrideOrdinal = rhs._isOverrideOrdinal;
+ _yAxisIndex = rhs._yAxisIndex;
+
+ if ( rhs.Tag is ICloneable )
+ this.Tag = ((ICloneable) rhs.Tag).Clone();
+ else
+ this.Tag = rhs.Tag;
+
+ _points = (IPointList) rhs.Points.Clone();
+
+ _link = rhs._link.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of Clone.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method must be called with an explicit cast to ICloneable, and
+ /// that it is inherently virtual. For example:
+ /// <code>
+ /// ParentClass foo = new ChildClass();
+ /// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
+ /// </code>
+ /// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
+ /// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
+ /// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
+ /// </remarks>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
+ //return new PaneBase( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected CurveItem( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _label = (Label) info.GetValue( "label", typeof(Label) );
+ _isY2Axis = info.GetBoolean( "isY2Axis" );
+ if ( sch >= 11 )
+ _isX2Axis = info.GetBoolean( "isX2Axis" );
+ else
+ _isX2Axis = false;
+
+ _isVisible = info.GetBoolean( "isVisible" );
+
+ _isOverrideOrdinal = info.GetBoolean( "isOverrideOrdinal" );
+
+ // Data Points are always stored as a PointPairList, regardless of the
+ // actual original type (which could be anything that supports IPointList).
+ _points = (PointPairList) info.GetValue( "points", typeof(PointPairList) );
+
+ Tag = info.GetValue( "Tag", typeof(object) );
+
+ _yAxisIndex = info.GetInt32( "yAxisIndex" );
+
+ _link = (Link) info.GetValue( "link", typeof(Link) );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "label", _label );
+ info.AddValue( "isY2Axis", _isY2Axis );
+ info.AddValue( "isX2Axis", _isX2Axis );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "isOverrideOrdinal", _isOverrideOrdinal );
+
+ // if points is already a PointPairList, use it
+ // otherwise, create a new PointPairList so it can be serialized
+ PointPairList list;
+ if ( _points is PointPairList )
+ list = _points as PointPairList;
+ else
+ list = new PointPairList( _points );
+
+ info.AddValue( "points", list );
+ info.AddValue( "Tag", Tag );
+ info.AddValue( "yAxisIndex", _yAxisIndex );
+
+ info.AddValue( "link", _link );
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// A <see cref="Label" /> instance that represents the <see cref="ZedGraph.Legend"/>
+ /// entry for the this <see cref="CurveItem"/> object
+ /// </summary>
+ public Label Label
+ {
+ get { return _label; }
+ set { _label = value;}
+ }
+
+ /// <summary>
+ /// The <see cref="Line"/>/<see cref="Symbol"/>/<see cref="Bar"/>
+ /// color (FillColor for the Bar). This is a common access to
+ /// <see cref="ZedGraph.LineBase.Color">Line.Color</see>,
+ /// <see cref="ZedGraph.LineBase.Color">Border.Color</see>, and
+ /// <see cref="ZedGraph.Fill.Color">Fill.Color</see> properties for this curve.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ if ( this is BarItem )
+ return ((BarItem) this).Bar.Fill.Color;
+ else if ( this is LineItem && ((LineItem) this).Line.IsVisible )
+ return ((LineItem) this).Line.Color;
+ else if ( this is LineItem )
+ return ((LineItem) this).Symbol.Border.Color;
+ else if ( this is ErrorBarItem )
+ return ((ErrorBarItem) this).Bar.Color;
+ else if ( this is HiLowBarItem )
+ return ((HiLowBarItem) this).Bar.Fill.Color;
+ else
+ return Color.Empty;
+ }
+ set
+ {
+ if ( this is BarItem )
+ {
+ ((BarItem) this).Bar.Fill.Color = value;
+ }
+ else if ( this is LineItem )
+ {
+ ((LineItem) this).Line.Color = value;
+ ((LineItem) this).Symbol.Border.Color = value;
+ ((LineItem) this).Symbol.Fill.Color = value;
+ }
+ else if ( this is ErrorBarItem )
+ ((ErrorBarItem) this).Bar.Color = value;
+ else if ( this is HiLowBarItem )
+ ((HiLowBarItem) this).Bar.Fill.Color = value;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether this <see cref="CurveItem"/> is visible on the graph.
+ /// Note that this value turns the curve display on or off, but it does not
+ /// affect the display of the legend entry. To hide the legend entry, you
+ /// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
+ /// </summary>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Determines whether this <see cref="CurveItem"/> is selected on the graph.
+ /// Note that this value changes the curve displayed color, but it does not
+ /// affect the display of the legend entry. To hide the legend entry, you
+ /// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
+ /// </summary>
+ public bool IsSelected
+ {
+ get { return _isSelected; }
+ set
+ {
+ _isSelected = value;
+
+ /*
+ if ( this is BarItem )
+ {
+ ( (BarItem)this ).Bar.Fill.UseInactiveColor = !value;
+ }
+ else if ( this is LineItem )
+ {
+ ( (LineItem)this ).Line.Fill.UseInactiveColor = !value;
+ ( (LineItem)this ).Symbol.Fill.UseInactiveColor = !value;
+ ( (LineItem)this ).Symbol.Fill.UseInactiveColor = !value;
+ }
+ else if ( this is HiLowBarItem )
+ ( (HiLowBarItem)this ).Bar.Fill.UseInactiveColor = !value;
+ else if ( this is PieItem )
+ ( (PieItem)this ).Fill.UseInactiveColor = !value;
+ */
+ }
+ }
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Determines whether this <see cref="CurveItem"/> can be selected in the graph.
+ /// </summary>
+ public bool IsSelectable
+ {
+ get { return _isSelectable; }
+ set { _isSelectable = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value which allows you to override the normal
+ /// ordinal axis behavior.
+ /// </summary>
+ /// <remarks>
+ /// Normally for an ordinal axis type, the actual data values corresponding to the ordinal
+ /// axis will be ignored (essentially they are replaced by ordinal values, e.g., 1, 2, 3, etc).
+ /// If IsOverrideOrdinal is true, then the user data values will be used (even if they don't
+ /// make sense). Fractional values are allowed, such that a value of 1.5 is between the first and
+ /// second ordinal position, etc.
+ /// </remarks>
+ /// <seealso cref="AxisType.Ordinal"/>
+ /// <seealso cref="AxisType.Text"/>
+ public bool IsOverrideOrdinal
+ {
+ get { return _isOverrideOrdinal; }
+ set { _isOverrideOrdinal = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which X axis this <see cref="CurveItem"/>
+ /// is assigned to.
+ /// </summary>
+ /// <remarks>
+ /// The
+ /// <see cref="ZedGraph.XAxis"/> is on the bottom side of the graph and the
+ /// <see cref="ZedGraph.X2Axis"/> is on the top side. Assignment to an axis
+ /// determines the scale that is used to draw the curve on the graph.
+ /// </remarks>
+ /// <value>true to assign the curve to the <see cref="ZedGraph.X2Axis"/>,
+ /// false to assign the curve to the <see cref="ZedGraph.XAxis"/></value>
+ public bool IsX2Axis
+ {
+ get { return _isX2Axis; }
+ set { _isX2Axis = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which Y axis this <see cref="CurveItem"/>
+ /// is assigned to.
+ /// </summary>
+ /// <remarks>
+ /// The
+ /// <see cref="ZedGraph.YAxis"/> is on the left side of the graph and the
+ /// <see cref="ZedGraph.Y2Axis"/> is on the right side. Assignment to an axis
+ /// determines the scale that is used to draw the curve on the graph. Note that
+ /// this value is used in combination with the <see cref="YAxisIndex" /> to determine
+ /// which of the Y Axes (if there are multiples) this curve belongs to.
+ /// </remarks>
+ /// <value>true to assign the curve to the <see cref="ZedGraph.Y2Axis"/>,
+ /// false to assign the curve to the <see cref="ZedGraph.YAxis"/></value>
+ public bool IsY2Axis
+ {
+ get { return _isY2Axis; }
+ set { _isY2Axis = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the index number of the Y Axis to which this
+ /// <see cref="CurveItem" /> belongs.
+ /// </summary>
+ /// <remarks>
+ /// This value is essentially an index number into the <see cref="GraphPane.YAxisList" />
+ /// or <see cref="GraphPane.Y2AxisList" />, depending on the setting of
+ /// <see cref="IsY2Axis" />.
+ /// </remarks>
+ public int YAxisIndex
+ {
+ get { return _yAxisIndex; }
+ set { _yAxisIndex = value; }
+ }
+
+ /// <summary>
+ /// Determines whether this <see cref="CurveItem"/>
+ /// is a <see cref="BarItem"/>.
+ /// </summary>
+ /// <value>true for a bar chart, or false for a line or pie graph</value>
+ public bool IsBar
+ {
+ get { return this is BarItem || this is HiLowBarItem || this is ErrorBarItem; }
+ }
+
+ /// <summary>
+ /// Determines whether this <see cref="CurveItem"/>
+ /// is a <see cref="PieItem"/>.
+ /// </summary>
+ /// <value>true for a pie chart, or false for a line or bar graph</value>
+ public bool IsPie
+ {
+ get { return this is PieItem; }
+ }
+
+ /// <summary>
+ /// Determines whether this <see cref="CurveItem"/>
+ /// is a <see cref="LineItem"/>.
+ /// </summary>
+ /// <value>true for a line chart, or false for a bar type</value>
+ public bool IsLine
+ {
+ get { return this is LineItem; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ abstract internal bool IsZIncluded( GraphPane pane );
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ abstract internal bool IsXIndependent( GraphPane pane );
+
+ /// <summary>
+ /// Readonly property that gives the number of points that define this
+ /// <see cref="CurveItem"/> object, which is the number of points in the
+ /// <see cref="Points"/> data collection.
+ /// </summary>
+ public int NPts
+ {
+ get
+ {
+ if ( _points == null )
+ return 0;
+ else
+ return _points.Count;
+ }
+ }
+
+ /// <summary>
+ /// The <see cref="IPointList"/> of X,Y point sets that represent this
+ /// <see cref="CurveItem"/>.
+ /// </summary>
+ public IPointList Points
+ {
+ get { return _points; }
+ set { _points = value; }
+ }
+
+ /// <summary>
+ /// An accessor for the <see cref="PointPair"/> datum for this <see cref="CurveItem"/>.
+ /// Index is the ordinal reference (zero based) of the point.
+ /// </summary>
+ public PointPair this[int index]
+ {
+ get
+ {
+ if ( _points == null )
+ return new PointPair( PointPair.Missing, PointPair.Missing );
+ else
+ return ( _points )[index];
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the hyperlink information for this <see cref="CurveItem" />.
+ /// </summary>
+ // /// <seealso cref="ZedGraph.Web.IsImageMap" />
+ public Link Link
+ {
+ get { return _link; }
+ set { _link = value; }
+ }
+
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Do all rendering associated with this <see cref="CurveItem"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">The ordinal position of the current <see cref="Bar"/>
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ abstract public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor );
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="CurveItem"/> at the specified location.
+ /// This abstract base method passes through to <see cref="BarItem.DrawLegendKey"/> or
+ /// <see cref="LineItem.DrawLegendKey"/> to do the rendering.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ abstract public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor );
+
+ #endregion
+
+ #region Utility Methods
+
+ /// <summary>
+ /// Add a single x,y coordinate point to the end of the points collection for this curve.
+ /// </summary>
+ /// <param name="x">The X coordinate value</param>
+ /// <param name="y">The Y coordinate value</param>
+ public void AddPoint( double x, double y )
+ {
+ this.AddPoint( new PointPair( x, y ) );
+ }
+
+ /// <summary>
+ /// Add a <see cref="PointPair"/> object to the end of the points collection for this curve.
+ /// </summary>
+ /// <remarks>
+ /// This method will only work if the <see cref="IPointList" /> instance reference
+ /// at <see cref="Points" /> supports the <see cref="IPointListEdit" /> interface.
+ /// Otherwise, it does nothing.
+ /// </remarks>
+ /// <param name="point">A reference to the <see cref="PointPair"/> object to
+ /// be added</param>
+ public void AddPoint( PointPair point )
+ {
+ if ( _points == null )
+ this.Points = new PointPairList();
+
+ if ( _points is IPointListEdit )
+ ( _points as IPointListEdit ).Add( point );
+ else
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Clears the points from this <see cref="CurveItem"/>. This is the same
+ /// as <c>CurveItem.Points.Clear()</c>.
+ /// </summary>
+ /// <remarks>
+ /// This method will only work if the <see cref="IPointList" /> instance reference
+ /// at <see cref="Points" /> supports the <see cref="IPointListEdit" /> interface.
+ /// Otherwise, it does nothing.
+ /// </remarks>
+ public void Clear()
+ {
+ if ( _points is IPointListEdit )
+ (_points as IPointListEdit).Clear();
+ else
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Removes a single point from this <see cref="CurveItem" />.
+ /// </summary>
+ /// <remarks>
+ /// This method will only work if the <see cref="IPointList" /> instance reference
+ /// at <see cref="Points" /> supports the <see cref="IPointListEdit" /> interface.
+ /// Otherwise, it does nothing.
+ /// </remarks>
+ /// <param name="index">The ordinal position of the point to be removed.</param>
+ public void RemovePoint( int index )
+ {
+ if ( _points is IPointListEdit )
+ (_points as IPointListEdit).RemoveAt( index );
+ else
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Get the X Axis instance (either <see cref="XAxis" /> or <see cref="X2Axis" />) to
+ /// which this <see cref="CurveItem" /> belongs.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> object to which this curve belongs.</param>
+ /// <returns>Either a <see cref="XAxis" /> or <see cref="X2Axis" /> to which this
+ /// <see cref="CurveItem" /> belongs.
+ /// </returns>
+ public Axis GetXAxis( GraphPane pane )
+ {
+ if ( _isX2Axis )
+ return pane.X2Axis;
+ else
+ return pane.XAxis;
+ }
+
+ /// <summary>
+ /// Get the Y Axis instance (either <see cref="YAxis" /> or <see cref="Y2Axis" />) to
+ /// which this <see cref="CurveItem" /> belongs.
+ /// </summary>
+ /// <remarks>
+ /// This method safely retrieves a Y Axis instance from either the <see cref="GraphPane.YAxisList" />
+ /// or the <see cref="GraphPane.Y2AxisList" /> using the values of <see cref="YAxisIndex" /> and
+ /// <see cref="IsY2Axis" />. If the value of <see cref="YAxisIndex" /> is out of bounds, the
+ /// default <see cref="YAxis" /> or <see cref="Y2Axis" /> is used.
+ /// </remarks>
+ /// <param name="pane">The <see cref="GraphPane" /> object to which this curve belongs.</param>
+ /// <returns>Either a <see cref="YAxis" /> or <see cref="Y2Axis" /> to which this
+ /// <see cref="CurveItem" /> belongs.
+ /// </returns>
+ public Axis GetYAxis( GraphPane pane )
+ {
+ if ( _isY2Axis )
+ {
+ if ( _yAxisIndex < pane.Y2AxisList.Count )
+ return pane.Y2AxisList[_yAxisIndex];
+ else
+ return pane.Y2AxisList[0];
+ }
+ else
+ {
+ if ( _yAxisIndex < pane.YAxisList.Count )
+ return pane.YAxisList[_yAxisIndex];
+ else
+ return pane.YAxisList[0];
+ }
+ }
+
+ /// <summary>
+ /// Get the index of the Y Axis in the <see cref="YAxis" /> or <see cref="Y2Axis" /> list to
+ /// which this <see cref="CurveItem" /> belongs.
+ /// </summary>
+ /// <remarks>
+ /// This method safely retrieves a Y Axis index into either the <see cref="GraphPane.YAxisList" />
+ /// or the <see cref="GraphPane.Y2AxisList" /> using the values of <see cref="YAxisIndex" /> and
+ /// <see cref="IsY2Axis" />. If the value of <see cref="YAxisIndex" /> is out of bounds, the
+ /// default <see cref="YAxis" /> or <see cref="Y2Axis" /> is used, which is index zero.
+ /// </remarks>
+ /// <param name="pane">The <see cref="GraphPane" /> object to which this curve belongs.</param>
+ /// <returns>An integer value indicating which index position in the list applies to this
+ /// <see cref="CurveItem" />
+ /// </returns>
+ public int GetYAxisIndex( GraphPane pane )
+ {
+ if ( _yAxisIndex >= 0 &&
+ _yAxisIndex < ( _isY2Axis ? pane.Y2AxisList.Count : pane.YAxisList.Count ) )
+ return _yAxisIndex;
+ else
+ return 0;
+ }
+
+ /// <summary>
+ /// Loads some pseudo unique colors/symbols into this CurveItem. This
+ /// is the same as <c>MakeUnique(ColorSymbolRotator.StaticInstance)</c>.
+ /// <seealso cref="ColorSymbolRotator.StaticInstance"/>
+ /// <seealso cref="ColorSymbolRotator"/>
+ /// <seealso cref="MakeUnique(ColorSymbolRotator)"/>
+ /// </summary>
+ public void MakeUnique()
+ {
+ this.MakeUnique( ColorSymbolRotator.StaticInstance );
+ }
+
+ /// <summary>
+ /// Loads some pseudo unique colors/symbols into this CurveItem. This
+ /// is mainly useful for differentiating a set of new CurveItems without
+ /// having to pick your own colors/symbols.
+ /// <seealso cref="MakeUnique(ColorSymbolRotator)"/>
+ /// </summary>
+ /// <param name="rotator">
+ /// The <see cref="ColorSymbolRotator"/> that is used to pick the color
+ /// and symbol for this method call.
+ /// </param>
+ virtual public void MakeUnique( ColorSymbolRotator rotator )
+ {
+ this.Color = rotator.NextColor;
+ }
+
+ /// <summary>
+ /// Go through the list of <see cref="PointPair"/> data values for this <see cref="CurveItem"/>
+ /// and determine the minimum and maximum values in the data.
+ /// </summary>
+ /// <param name="xMin">The minimum X value in the range of data</param>
+ /// <param name="xMax">The maximum X value in the range of data</param>
+ /// <param name="yMin">The minimum Y value in the range of data</param>
+ /// <param name="yMax">The maximum Y value in the range of data</param>
+ /// <param name="ignoreInitial">ignoreInitial is a boolean value that
+ /// affects the data range that is considered for the automatic scale
+ /// ranging (see <see cref="GraphPane.IsIgnoreInitial"/>). If true, then initial
+ /// data points where the Y value is zero are not included when
+ /// automatically determining the scale <see cref="Scale.Min"/>,
+ /// <see cref="Scale.Max"/>, and <see cref="Scale.MajorStep"/> size. All data after
+ /// the first non-zero Y value are included.
+ /// </param>
+ /// <param name="isBoundedRanges">
+ /// Determines if the auto-scaled axis ranges will subset the
+ /// data points based on any manually set scale range values.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <seealso cref="GraphPane.IsBoundedRanges"/>
+ virtual public void GetRange( out double xMin, out double xMax,
+ out double yMin, out double yMax,
+ bool ignoreInitial,
+ bool isBoundedRanges,
+ GraphPane pane )
+ {
+ // The lower and upper bounds of allowable data for the X values. These
+ // values allow you to subset the data values. If the X range is bounded, then
+ // the resulting range for Y will reflect the Y values for the points within the X
+ // bounds.
+ double xLBound = double.MinValue;
+ double xUBound = double.MaxValue;
+ double yLBound = double.MinValue;
+ double yUBound = double.MaxValue;
+
+ // initialize the values to outrageous ones to start
+ xMin = yMin = Double.MaxValue;
+ xMax = yMax = Double.MinValue;
+
+ Axis yAxis = this.GetYAxis( pane );
+ Axis xAxis = this.GetXAxis( pane );
+ if ( yAxis == null || xAxis == null )
+ return;
+
+ if ( isBoundedRanges )
+ {
+ xLBound = xAxis._scale._lBound;
+ xUBound = xAxis._scale._uBound;
+ yLBound = yAxis._scale._lBound;
+ yUBound = yAxis._scale._uBound;
+ }
+
+
+ bool isZIncluded = this.IsZIncluded( pane );
+ bool isXIndependent = this.IsXIndependent( pane );
+ bool isXLog = xAxis.Scale.IsLog;
+ bool isYLog = yAxis.Scale.IsLog;
+ bool isXOrdinal = xAxis.Scale.IsAnyOrdinal;
+ bool isYOrdinal = yAxis.Scale.IsAnyOrdinal;
+ bool isZOrdinal = ( isXIndependent ? yAxis : xAxis ).Scale.IsAnyOrdinal;
+
+ // Loop over each point in the arrays
+ //foreach ( PointPair point in this.Points )
+ for ( int i=0; i<this.Points.Count; i++ )
+ {
+ PointPair point = this.Points[i];
+
+ double curX = isXOrdinal ? i + 1 : point.X;
+ double curY = isYOrdinal ? i + 1 : point.Y;
+ double curZ = isZOrdinal ? i + 1 : point.Z;
+
+ bool outOfBounds = curX < xLBound || curX > xUBound ||
+ curY < yLBound || curY > yUBound ||
+ ( isZIncluded && isXIndependent && ( curZ < yLBound || curZ > yUBound ) ) ||
+ ( isZIncluded && !isXIndependent && ( curZ < xLBound || curZ > xUBound ) ) ||
+ ( curX <= 0 && isXLog ) || ( curY <= 0 && isYLog );
+
+ // ignoreInitial becomes false at the first non-zero
+ // Y value
+ if ( ignoreInitial && curY != 0 &&
+ curY != PointPair.Missing )
+ ignoreInitial = false;
+
+ if ( !ignoreInitial &&
+ !outOfBounds &&
+ curX != PointPair.Missing &&
+ curY != PointPair.Missing )
+ {
+ if ( curX < xMin )
+ xMin = curX;
+ if ( curX > xMax )
+ xMax = curX;
+ if ( curY < yMin )
+ yMin = curY;
+ if ( curY > yMax )
+ yMax = curY;
+
+ if ( isZIncluded && isXIndependent && curZ != PointPair.Missing )
+ {
+ if ( curZ < yMin )
+ yMin = curZ;
+ if ( curZ > yMax )
+ yMax = curZ;
+ }
+ else if ( isZIncluded && curZ != PointPair.Missing )
+ {
+ if ( curZ < xMin )
+ xMin = curZ;
+ if ( curZ > xMax )
+ xMax = curZ;
+ }
+ }
+ }
+ }
+
+ /// <summary>Returns a reference to the <see cref="Axis"/> object that is the "base"
+ /// (independent axis) from which the values are drawn. </summary>
+ /// <remarks>
+ /// This property is determined by the value of <see cref="BarSettings.Base"/> for
+ /// <see cref="BarItem"/>, <see cref="ErrorBarItem"/>, and <see cref="HiLowBarItem"/>
+ /// types. It is always the X axis for regular <see cref="LineItem"/> types.
+ /// Note that the <see cref="BarSettings.Base" /> setting can override the
+ /// <see cref="IsY2Axis" /> and <see cref="YAxisIndex" /> settings for bar types
+ /// (this is because all the bars that are clustered together must share the
+ /// same base axis).
+ /// </remarks>
+ /// <seealso cref="BarBase"/>
+ /// <seealso cref="ValueAxis"/>
+ public virtual Axis BaseAxis( GraphPane pane )
+ {
+ BarBase barBase;
+
+ if ( this is BarItem || this is ErrorBarItem || this is HiLowBarItem )
+ barBase = pane._barSettings.Base;
+ else
+ barBase = _isX2Axis ? BarBase.X2 : BarBase.X;
+
+ if ( barBase == BarBase.X )
+ return pane.XAxis;
+ else if ( barBase == BarBase.X2 )
+ return pane.X2Axis;
+ else if ( barBase == BarBase.Y )
+ return pane.YAxis;
+ else
+ return pane.Y2Axis;
+
+ }
+ /// <summary>Returns a reference to the <see cref="Axis"/> object that is the "value"
+ /// (dependent axis) from which the points are drawn. </summary>
+ /// <remarks>
+ /// This property is determined by the value of <see cref="BarSettings.Base"/> for
+ /// <see cref="BarItem"/>, <see cref="ErrorBarItem"/>, and <see cref="HiLowBarItem"/>
+ /// types. It is always the Y axis for regular <see cref="LineItem"/> types.
+ /// </remarks>
+ /// <seealso cref="BarBase"/>
+ /// <seealso cref="BaseAxis"/>
+ public virtual Axis ValueAxis( GraphPane pane )
+ {
+ BarBase barBase;
+
+ if ( this is BarItem || this is ErrorBarItem || this is HiLowBarItem )
+ barBase = pane._barSettings.Base;
+ else
+ barBase = BarBase.X;
+
+ if ( barBase == BarBase.X || barBase == BarBase.X2 )
+ {
+ return GetYAxis( pane );
+ }
+ else
+ return GetXAxis( pane );
+ }
+
+ /// <summary>
+ /// Calculate the width of each bar, depending on the actual bar type
+ /// </summary>
+ /// <returns>The width for an individual bar, in pixel units</returns>
+ public float GetBarWidth( GraphPane pane )
+ {
+ // Total axis width =
+ // npts * ( nbars * ( bar + bargap ) - bargap + clustgap )
+ // cg * bar = cluster gap
+ // npts = max number of points in any curve
+ // nbars = total number of curves that are of type IsBar
+ // bar = bar width
+ // bg * bar = bar gap
+ // therefore:
+ // totwidth = npts * ( nbars * (bar + bg*bar) - bg*bar + cg*bar )
+ // totwidth = bar * ( npts * ( nbars * ( 1 + bg ) - bg + cg ) )
+ // solve for bar
+
+ float barWidth;
+
+ if ( this is ErrorBarItem )
+ barWidth = (float) ( ((ErrorBarItem)this).Bar.Symbol.Size *
+ pane.CalcScaleFactor() );
+// else if ( this is HiLowBarItem && pane._barSettings.Type != BarType.ClusterHiLow )
+// barWidth = (float) ( ((HiLowBarItem)this).Bar.GetBarWidth( pane,
+// ((HiLowBarItem)this).BaseAxis(pane), pane.CalcScaleFactor() ) );
+// barWidth = (float) ( ((HiLowBarItem)this).Bar.Size *
+// pane.CalcScaleFactor() );
+ else // BarItem or LineItem
+ {
+ // For stacked bar types, the bar width will be based on a single bar
+ float numBars = 1.0F;
+ if ( pane._barSettings.Type == BarType.Cluster )
+ numBars = pane.CurveList.NumClusterableBars;
+
+ float denom = numBars * ( 1.0F + pane._barSettings.MinBarGap ) -
+ pane._barSettings.MinBarGap + pane._barSettings.MinClusterGap;
+ if ( denom <= 0 )
+ denom = 1;
+ barWidth = pane.BarSettings.GetClusterWidth() / denom;
+ }
+
+ if ( barWidth <= 0 )
+ return 1;
+
+ return barWidth;
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ abstract public bool GetCoords( GraphPane pane, int i, out string coords );
+
+ #endregion
+
+ #region Inner classes
+
+ #if ( DOTNET1 ) // Is this a .Net 1.1 compilation?
+
+ /// <summary>
+ /// Compares <see cref="CurveItem"/>'s based on the point value at the specified
+ /// index and for the specified axis.
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/>
+ /// </summary>
+ public class Comparer : IComparer
+ {
+ private int index;
+ private SortType sortType;
+
+ /// <summary>
+ /// Constructor for Comparer.
+ /// </summary>
+ /// <param name="type">The axis type on which to sort.</param>
+ /// <param name="index">The index number of the point on which to sort</param>
+ public Comparer( SortType type, int index )
+ {
+ this.sortType = type;
+ this.index = index;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="CurveItem"/>s using the previously specified index value
+ /// and axis. Sorts in descending order.
+ /// </summary>
+ /// <param name="l">Curve to the left.</param>
+ /// <param name="r">Curve to the right.</param>
+ /// <returns>-1, 0, or 1 depending on l.X's relation to r.X</returns>
+ public int Compare( object l, object r )
+ {
+ CurveItem cl = (CurveItem) l;
+ CurveItem cr = (CurveItem) r;
+
+ if (cl == null && cr == null )
+ return 0;
+ else if (cl == null && cr != null )
+ return -1;
+ else if (cl != null && cr == null)
+ return 1;
+
+ if ( cr != null && cr.NPts <= index )
+ cr = null;
+ if ( cl != null && cl.NPts <= index )
+ cl = null;
+
+ double lVal, rVal;
+
+ if ( sortType == SortType.XValues )
+ {
+ lVal = ( l != null ) ? System.Math.Abs( cl[index].X ) : PointPair.Missing;
+ rVal = ( r != null ) ? System.Math.Abs( cr[index].X ) : PointPair.Missing;
+ }
+ else
+ {
+ lVal = ( l != null ) ? System.Math.Abs( cl[index].Y ) : PointPair.Missing;
+ rVal = ( r != null ) ? System.Math.Abs( cr[index].Y ) : PointPair.Missing;
+ }
+
+ if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
+ cl = null;
+ if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
+ cr = null;
+
+ if ( ( cl == null && cr == null) || ( System.Math.Abs( lVal - rVal ) < 1e-10 ) )
+ return 0;
+ else if ( cl == null && cr != null )
+ return -1;
+ else if ( cl != null && r == null )
+ return 1;
+ else
+ return rVal < lVal ? -1 : 1;
+ }
+ }
+
+#else // Otherwise, it's .Net 2.0 so use generics
+
+ /// <summary>
+ /// Compares <see cref="CurveItem"/>'s based on the point value at the specified
+ /// index and for the specified axis.
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/>
+ /// </summary>
+ public class Comparer : IComparer<CurveItem>
+ {
+ private int index;
+ private SortType sortType;
+
+ /// <summary>
+ /// Constructor for Comparer.
+ /// </summary>
+ /// <param name="type">The axis type on which to sort.</param>
+ /// <param name="index">The index number of the point on which to sort</param>
+ public Comparer( SortType type, int index )
+ {
+ this.sortType = type;
+ this.index = index;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="CurveItem"/>s using the previously specified index value
+ /// and axis. Sorts in descending order.
+ /// </summary>
+ /// <param name="l">Curve to the left.</param>
+ /// <param name="r">Curve to the right.</param>
+ /// <returns>-1, 0, or 1 depending on l.X's relation to r.X</returns>
+ public int Compare( CurveItem? l, CurveItem? r )
+ {
+ if (l == null && r == null )
+ return 0;
+ else if (l == null && r != null )
+ return -1;
+ else if (l != null && r == null)
+ return 1;
+
+ if ( r != null && r.NPts <= index )
+ r = null;
+ if ( l != null && l.NPts <= index )
+ l = null;
+
+ double lVal, rVal;
+
+ if ( sortType == SortType.XValues )
+ {
+ lVal = ( l != null ) ? System.Math.Abs( l[index].X ) : PointPair.Missing;
+ rVal = ( r != null ) ? System.Math.Abs( r[index].X ) : PointPair.Missing;
+ }
+ else
+ {
+ lVal = ( l != null ) ? System.Math.Abs( l[index].Y ) : PointPair.Missing;
+ rVal = ( r != null ) ? System.Math.Abs( r[index].Y ) : PointPair.Missing;
+ }
+
+ if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
+ l = null;
+ if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
+ r = null;
+
+ if ( (l == null && r == null) || ( System.Math.Abs( lVal - rVal ) < 1e-10 ) )
+ return 0;
+ else if (l == null && r != null )
+ return -1;
+ else if (l != null && r == null)
+ return 1;
+ else
+ return rVal < lVal ? -1 : 1;
+ }
+ }
+
+ #endif
+
+ #endregion
+
+ }
+}
+
+
+
diff --git a/ZedGraph/CurveList.cs b/ZedGraph/CurveList.cs
new file mode 100644
index 0000000..4182822
--- /dev/null
+++ b/ZedGraph/CurveList.cs
@@ -0,0 +1,745 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="CurveItem"/> objects
+ /// that define the set of curves to be displayed on the graph.
+ /// </summary>
+ ///
+ /// <author> John Champion
+ /// modified by Jerry Vos</author>
+ /// <version> $Revision: 3.43 $ $Date: 2007-11-03 04:41:28 $ </version>
+ [Serializable]
+ public class CurveList : List<CurveItem>, ICloneable
+ {
+
+ #region Properties
+ // internal temporary value that keeps
+ // the max number of points for any curve
+ // associated with this curveList
+ private int maxPts;
+
+ /// <summary>
+ /// Read only value for the maximum number of points in any of the curves
+ /// in the list.
+ /// </summary>
+ public int MaxPts
+ {
+ get { return maxPts; }
+ }
+
+ /// <summary>
+ /// Read only property that returns the number of curves in the list that are of
+ /// type <see cref="BarItem"/>. This does not include <see cref="HiLowBarItem" /> or
+ /// <see cref="ErrorBarItem" /> types.
+ /// </summary>
+ public int NumBars
+ {
+ get
+ {
+ int count = 0;
+ foreach ( CurveItem curve in this )
+ {
+ if ( curve.IsBar )
+ count++;
+ }
+
+ return count;
+ }
+ }
+
+ /// <summary>
+ /// Read only property that returns the number of curves in the list that are
+ /// potentially "clusterable", which includes <see cref="BarItem"/> and
+ /// <see cref="HiLowBarItem" /> types. This does not include <see cref="ErrorBarItem" />,
+ /// <see cref="OHLCBarItem" />, <see cref="JapaneseCandleStickItem" />, etc. types.
+ /// </summary>
+ /// <remarks>Note that this property is only the number of bars that COULD BE clustered. The
+ /// actual cluster settings are not considered.</remarks>
+ public int NumClusterableBars
+ {
+ get
+ {
+ int count = 0;
+ foreach ( CurveItem curve in this )
+ {
+ if ( curve.IsBar || curve is HiLowBarItem )
+ count++;
+ }
+
+ return count;
+ }
+ }
+
+
+
+ /// <summary>
+ /// Read only property that returns the number of pie slices in the list (class type is
+ /// <see cref="PieItem"/> ).
+ /// </summary>
+ public int NumPies
+ {
+ get
+ {
+ int count = 0;
+ foreach ( CurveItem curve in this )
+ {
+ if ( curve.IsPie )
+ count++;
+ }
+
+ return count;
+ }
+ }
+
+ /// <summary>
+ /// Read only property that determines if all items in the <see cref="CurveList"/> are
+ /// Pies.
+ /// </summary>
+ public bool IsPieOnly
+ {
+ get
+ {
+ bool hasPie = false;
+ foreach ( CurveItem curve in this )
+ {
+ if ( !curve.IsPie )
+ return false;
+ else
+ hasPie = true;
+ }
+ return hasPie;
+ }
+ }
+
+ /// <summary>
+ /// Determine if there is any data in any of the <see cref="CurveItem"/>
+ /// objects for this graph. This method does not verify valid data, it
+ /// only checks to see if <see cref="CurveItem.NPts"/> > 0.
+ /// </summary>
+ /// <returns>true if there is any data, false otherwise</returns>
+ public bool HasData()
+ {
+ foreach( CurveItem curve in this )
+ {
+ if ( curve.Points.Count > 0 )
+ return true;
+ }
+ return false;
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the collection class
+ /// </summary>
+ public CurveList()
+ {
+ maxPts = 1;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The XAxis object from which to copy</param>
+ public CurveList( CurveList rhs )
+ {
+ this.maxPts = rhs.maxPts;
+
+ foreach ( CurveItem item in rhs )
+ {
+ this.Add( (CurveItem) ((ICloneable)item).Clone() );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public CurveList Clone()
+ {
+ return new CurveList( this );
+ }
+
+
+ #endregion
+
+ #region IEnumerable Methods
+
+ //CJBL
+ /// <summary>
+ /// Iterate backwards through the <see cref="CurveList" /> items.
+ /// </summary>
+ public IEnumerable<CurveItem> Backward
+ {
+ get
+ {
+ for ( int i = this.Count - 1; i >= 0; i-- )
+ yield return this[i];
+ }
+ }
+ /// <summary>
+ /// Iterate forward through the <see cref="CurveList" /> items.
+ /// </summary>
+ public IEnumerable<CurveItem> Forward
+ {
+ get
+ {
+ for ( int i = 0; i < this.Count; i++ )
+ yield return this[i];
+ }
+ }
+
+ #endregion
+
+ #region List Methods
+/*
+ /// <summary>
+ /// Indexer to access the specified <see cref="CurveItem"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="CurveItem"/> object to be accessed.</param>
+ /// <value>A <see cref="CurveItem"/> object reference.</value>
+ public CurveItem this[ int index ]
+ {
+ get { return( (CurveItem) List[index] ); }
+ set { List[index] = value; }
+ }
+*/
+ /// <summary>
+ /// Indexer to access the specified <see cref="CurveItem"/> object by
+ /// its <see cref="CurveItem.Label"/> string.
+ /// </summary>
+ /// <param name="label">The string label of the
+ /// <see cref="CurveItem"/> object to be accessed.</param>
+ /// <value>A <see cref="CurveItem"/> object reference.</value>
+ public CurveItem this[ string label ]
+ {
+ get
+ {
+ int index = IndexOf( label );
+ if ( index >= 0 )
+ return( this[index] );
+ else
+ return null;
+ }
+ }
+/*
+ /// <summary>
+ /// Add a <see cref="CurveItem"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="curve">A reference to the <see cref="CurveItem"/> object to
+ /// be added</param>
+ /// <seealso cref="IList.Add"/>
+ public void Add( CurveItem curve )
+ {
+ List.Add( curve );
+ }
+*/
+/*
+ /// <summary>
+ /// Remove a <see cref="CurveItem"/> object from the collection based on an object reference.
+ /// </summary>
+ /// <param name="curve">A reference to the <see cref="CurveItem"/> object that is to be
+ /// removed.</param>
+ /// <seealso cref="IList.Remove"/>
+ public void Remove( CurveItem curve )
+ {
+ List.Remove( curve );
+ }
+*/
+/*
+ /// <summary>
+ /// Insert a <see cref="CurveItem"/> object into the collection at the specified
+ /// zero-based index location.
+ /// </summary>
+ /// <param name="index">The zero-based index location for insertion.</param>
+ /// <param name="curve">A reference to the <see cref="CurveItem"/> object that is to be
+ /// inserted.</param>
+ /// <seealso cref="IList.Insert"/>
+ public void Insert( int index, CurveItem curve )
+ {
+ List.Insert( index, curve );
+ }
+*/
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="CurveItem"/> with the specified <see cref="CurveItem.Label"/>.
+ /// </summary>
+ /// <param name="label">The <see cref="String"/> label that is in the
+ /// <see cref="CurveItem.Label"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="CurveItem"/>,
+ /// or -1 if the <see cref="CurveItem"/> is not in the list</returns>
+ /// <seealso cref="IndexOfTag"/>
+ public int IndexOf( string label )
+ {
+ int index = 0;
+ foreach ( CurveItem p in this )
+ {
+ if ( String.Compare( p._label._text, label, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="CurveItem"/> with the specified <see cref="CurveItem.Tag"/>.
+ /// </summary>
+ /// <remarks>In order for this method to work, the <see cref="CurveItem.Tag"/>
+ /// property must be of type <see cref="String"/>.</remarks>
+ /// <param name="tag">The <see cref="String"/> tag that is in the
+ /// <see cref="CurveItem.Tag"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="CurveItem"/>,
+ /// or -1 if the <see cref="CurveItem"/> is not in the list</returns>
+ public int IndexOfTag( string tag )
+ {
+ int index = 0;
+ foreach ( CurveItem p in this )
+ {
+ if ( p.Tag is string &&
+ String.Compare( (string) p.Tag, tag, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Sorts the list according to the point values at the specified index and
+ /// for the specified axis.
+ /// </summary>
+ public void Sort( SortType type, int index )
+ {
+ this.Sort( new CurveItem.Comparer( type, index ) );
+ }
+
+ /// <summary>
+ /// Move the position of the object at the specified index
+ /// to the new relative position in the list.</summary>
+ /// <remarks>For Graphic type objects, this method controls the
+ /// Z-Order of the items. Objects at the beginning of the list
+ /// appear in front of objects at the end of the list.</remarks>
+ /// <param name="index">The zero-based index of the object
+ /// to be moved.</param>
+ /// <param name="relativePos">The relative number of positions to move
+ /// the object. A value of -1 will move the
+ /// object one position earlier in the list, a value
+ /// of 1 will move it one position later. To move an item to the
+ /// beginning of the list, use a large negative value (such as -999).
+ /// To move it to the end of the list, use a large positive value.
+ /// </param>
+ /// <returns>The new position for the object, or -1 if the object
+ /// was not found.</returns>
+ public int Move( int index, int relativePos )
+ {
+ if ( index < 0 || index >= Count )
+ return -1;
+
+ CurveItem curve = this[index];
+ this.RemoveAt( index );
+
+ index += relativePos;
+ if ( index < 0 )
+ index = 0;
+ if ( index > Count )
+ index = Count;
+
+ Insert( index, curve );
+ return index;
+ }
+
+
+
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Go through each <see cref="CurveItem"/> object in the collection,
+ /// calling the <see cref="CurveItem.GetRange"/> member to
+ /// determine the minimum and maximum values in the
+ /// <see cref="CurveItem.Points"/> list of data value pairs. If the curves include
+ /// a stack bar, handle within the current GetRange method. In the event that no
+ /// data are available, a default range of min=0.0 and max=1.0 are returned.
+ /// If the Y axis has a valid data range and the Y2 axis not, then the Y2
+ /// range will be a duplicate of the Y range. Vice-versa for the Y2 axis
+ /// having valid data when the Y axis does not.
+ /// If any <see cref="CurveItem"/> in the list has a missing
+ /// <see cref="PointPairList"/>, a new empty one will be generated.
+ /// </summary>
+ /// <param name="bIgnoreInitial">ignoreInitial is a boolean value that
+ /// affects the data range that is considered for the automatic scale
+ /// ranging (see <see cref="GraphPane.IsIgnoreInitial"/>). If true, then initial
+ /// data points where the Y value is zero are not included when
+ /// automatically determining the scale <see cref="Scale.Min"/>,
+ /// <see cref="Scale.Max"/>, and <see cref="Scale.MajorStep"/> size. All data after
+ /// the first non-zero Y value are included.
+ /// </param>
+ /// <param name="isBoundedRanges">
+ /// Determines if the auto-scaled axis ranges will subset the
+ /// data points based on any manually set scale range values.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <seealso cref="GraphPane.IsBoundedRanges"/>
+ public void GetRange( bool bIgnoreInitial, bool isBoundedRanges, GraphPane pane )
+ {
+ double tXMinVal,
+ tXMaxVal,
+ tYMinVal,
+ tYMaxVal;
+
+ InitScale( pane.XAxis.Scale, isBoundedRanges );
+ InitScale( pane.X2Axis.Scale, isBoundedRanges );
+
+ foreach ( YAxis axis in pane.YAxisList )
+ InitScale( axis.Scale, isBoundedRanges );
+
+ foreach ( Y2Axis axis in pane.Y2AxisList )
+ InitScale( axis.Scale, isBoundedRanges );
+
+ maxPts = 1;
+
+ // Loop over each curve in the collection and examine the data ranges
+ foreach ( CurveItem curve in this )
+ {
+ if ( curve.IsVisible )
+ {
+ // For stacked types, use the GetStackRange() method which accounts for accumulated values
+ // rather than simple curve values.
+ if ( ( ( curve is BarItem ) && ( pane._barSettings.Type == BarType.Stack ||
+ pane._barSettings.Type == BarType.PercentStack ) ) ||
+ ( ( curve is LineItem ) && pane.LineType == LineType.Stack ) )
+ {
+ GetStackRange( pane, curve, out tXMinVal, out tYMinVal,
+ out tXMaxVal, out tYMaxVal );
+ }
+ else
+ {
+ // Call the GetRange() member function for the current
+ // curve to get the min and max values
+ curve.GetRange( out tXMinVal, out tXMaxVal,
+ out tYMinVal, out tYMaxVal, bIgnoreInitial, true, pane );
+ }
+
+ // isYOrd is true if the Y axis is an ordinal type
+ Scale yScale = curve.GetYAxis( pane ).Scale;
+
+ Scale xScale = curve.GetXAxis( pane ).Scale;
+ bool isYOrd = yScale.IsAnyOrdinal;
+ // isXOrd is true if the X axis is an ordinal type
+ bool isXOrd = xScale.IsAnyOrdinal;
+
+ // For ordinal Axes, the data range is just 1 to Npts
+ if ( isYOrd && !curve.IsOverrideOrdinal )
+ {
+ tYMinVal = 1.0;
+ tYMaxVal = curve.NPts;
+ }
+ if ( isXOrd && !curve.IsOverrideOrdinal )
+ {
+ tXMinVal = 1.0;
+ tXMaxVal = curve.NPts;
+ }
+
+ // Bar types always include the Y=0 value
+ if ( curve.IsBar )
+ {
+ if ( pane._barSettings.Base == BarBase.X ||
+ pane._barSettings.Base == BarBase.X2 )
+ {
+ // Only force z=0 for BarItems, not HiLowBarItems
+ if ( ! (curve is HiLowBarItem) )
+ {
+ if ( tYMinVal > 0 )
+ tYMinVal = 0;
+ else if ( tYMaxVal < 0 )
+ tYMaxVal = 0;
+ }
+
+ // for non-ordinal axes, expand the data range slightly for bar charts to
+ // account for the fact that the bar clusters have a width
+ if ( !isXOrd )
+ {
+ tXMinVal -= pane._barSettings._clusterScaleWidth / 2.0;
+ tXMaxVal += pane._barSettings._clusterScaleWidth / 2.0;
+ }
+ }
+ else
+ {
+ // Only force z=0 for BarItems, not HiLowBarItems
+ if ( !( curve is HiLowBarItem ) )
+ {
+ if ( tXMinVal > 0 )
+ tXMinVal = 0;
+ else if ( tXMaxVal < 0 )
+ tXMaxVal = 0;
+ }
+
+ // for non-ordinal axes, expand the data range slightly for bar charts to
+ // account for the fact that the bar clusters have a width
+ if ( !isYOrd )
+ {
+ tYMinVal -= pane._barSettings._clusterScaleWidth / 2.0;
+ tYMaxVal += pane._barSettings._clusterScaleWidth / 2.0;
+ }
+ }
+ }
+
+ // determine which curve has the maximum number of points
+ if ( curve.NPts > maxPts )
+ maxPts = curve.NPts;
+
+ // If the min and/or max values from the current curve
+ // are the absolute min and/or max, then save the values
+ // Also, differentiate between Y and Y2 values
+
+ if ( tYMinVal < yScale._rangeMin )
+ yScale._rangeMin = tYMinVal;
+ if ( tYMaxVal > yScale._rangeMax )
+ yScale._rangeMax = tYMaxVal;
+
+
+ if ( tXMinVal < xScale._rangeMin )
+ xScale._rangeMin = tXMinVal;
+ if ( tXMaxVal > xScale._rangeMax )
+ xScale._rangeMax = tXMaxVal;
+ }
+ }
+
+ pane.XAxis.Scale.SetRange( pane, pane.XAxis );
+ pane.X2Axis.Scale.SetRange( pane, pane.X2Axis );
+
+ foreach ( YAxis axis in pane.YAxisList )
+ axis.Scale.SetRange( pane, axis );
+ foreach ( Y2Axis axis in pane.Y2AxisList )
+ axis.Scale.SetRange( pane, axis );
+ }
+
+ private void InitScale( Scale scale, bool isBoundedRanges )
+ {
+ scale._rangeMin = double.MaxValue;
+ scale._rangeMax = double.MinValue;
+ scale._lBound = ( isBoundedRanges && !scale._minAuto ) ?
+ scale._min : double.MinValue;
+ scale._uBound = ( isBoundedRanges && !scale._maxAuto ) ?
+ scale._max : double.MaxValue;
+ }
+
+ /// <summary>
+ /// Calculate the range for stacked bars and lines.
+ /// </summary>
+ /// <remarks>This method is required for the stacked
+ /// types because (for bars), the negative values are a separate stack than the positive
+ /// values. If you just sum up the bars, you will get the sum of the positive plus negative,
+ /// which is less than the maximum positive value and greater than the maximum negative value.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">The <see cref="CurveItem"/> for which to calculate the range</param>
+ /// <param name="tXMinVal">The minimum X value so far</param>
+ /// <param name="tYMinVal">The minimum Y value so far</param>
+ /// <param name="tXMaxVal">The maximum X value so far</param>
+ /// <param name="tYMaxVal">The maximum Y value so far</param>
+ /// <seealso cref="GraphPane.IsBoundedRanges"/>
+ private void GetStackRange( GraphPane pane, CurveItem curve, out double tXMinVal,
+ out double tYMinVal, out double tXMaxVal, out double tYMaxVal )
+ {
+ // initialize the values to outrageous ones to start
+ tXMinVal = tYMinVal = Double.MaxValue;
+ tXMaxVal = tYMaxVal = Double.MinValue;
+
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ Axis baseAxis = curve.BaseAxis( pane );
+ bool isXBase = baseAxis is XAxis || baseAxis is X2Axis;
+
+ double lowVal, baseVal, hiVal;
+
+ for ( int i=0; i<curve.Points.Count; i++ )
+ {
+ valueHandler.GetValues( curve, i, out baseVal, out lowVal, out hiVal );
+ double x = isXBase ? baseVal : hiVal;
+ double y = isXBase ? hiVal : baseVal;
+
+ if ( x != PointPair.Missing && y != PointPair.Missing && lowVal != PointPair.Missing )
+ {
+ if ( x < tXMinVal )
+ tXMinVal = x;
+ if ( x > tXMaxVal )
+ tXMaxVal = x;
+ if ( y < tYMinVal )
+ tYMinVal = y;
+ if ( y > tYMaxVal )
+ tYMaxVal = y;
+
+ if ( !isXBase )
+ {
+ if ( lowVal < tXMinVal )
+ tXMinVal = lowVal;
+ if ( lowVal > tXMaxVal )
+ tXMaxVal = lowVal;
+ }
+ else
+ {
+ if ( lowVal < tYMinVal )
+ tYMinVal = lowVal;
+ if ( lowVal > tYMaxVal )
+ tYMaxVal = lowVal;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Render all the <see cref="CurveItem"/> objects in the list to the
+ /// specified <see cref="Graphics"/>
+ /// device by calling the <see cref="CurveItem.Draw"/> member function of
+ /// each <see cref="CurveItem"/> object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, float scaleFactor )
+ {
+ // Configure the accumulator for stacked bars
+ //Bar.ResetBarStack();
+
+ // Count the number of BarItems in the curvelist
+ int pos = this.NumBars;
+
+ // sorted overlay bars are a special case, since they are sorted independently at each
+ // ordinal position.
+ if ( pane._barSettings.Type == BarType.SortedOverlay )
+ {
+ // First, create a new curveList with references (not clones) of the curves
+ CurveList tempList = new CurveList();
+ foreach ( CurveItem curve in this )
+ if ( curve.IsBar )
+ tempList.Add( (CurveItem) curve );
+
+ // Loop through the bars, graphing each ordinal position separately
+ for ( int i=0; i<this.maxPts; i++ )
+ {
+ // At each ordinal position, sort the curves according to the value axis value
+ tempList.Sort( pane._barSettings.Base == BarBase.X ? SortType.YValues : SortType.XValues, i );
+ // plot the bars for the current ordinal position, in sorted order
+ foreach ( BarItem barItem in tempList )
+ barItem.Bar.DrawSingleBar( g, pane, barItem,
+ ((BarItem)barItem).BaseAxis( pane ),
+ ((BarItem)barItem).ValueAxis( pane ),
+ 0, i, ( (BarItem)barItem ).GetBarWidth( pane ), scaleFactor );
+ }
+ }
+
+ // Loop for each curve in reverse order to pick up the remaining curves
+ // The reverse order is done so that curves that are later in the list are plotted behind
+ // curves that are earlier in the list
+
+ for ( int i = this.Count - 1; i >= 0; i-- )
+ {
+ CurveItem curve = this[i];
+
+ if ( curve.IsBar)
+ pos--;
+
+ // Render the curve
+
+ // if it's a sorted overlay bar type, it's already been done above
+ if ( !( curve.IsBar && pane._barSettings.Type == BarType.SortedOverlay ) )
+ {
+ curve.Draw( g, pane, pos, scaleFactor );
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Find the ordinal position of the specified <see cref="BarItem" /> within
+ /// the <see cref="CurveList" />. This position only counts <see cef="BarItem" />
+ /// types, ignoring all other types.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> of interest</param>
+ /// <param name="barItem">The <see cref="BarItem" /> for which to search.</param>
+ /// <returns>The ordinal position of the specified bar, or -1 if the bar
+ /// was not found.</returns>
+ public int GetBarItemPos( GraphPane pane, BarItem barItem )
+ {
+ if ( pane._barSettings.Type == BarType.Overlay ||
+ pane._barSettings.Type == BarType.Stack ||
+ pane._barSettings.Type == BarType.PercentStack)
+ return 0;
+
+ int i = 0;
+ foreach ( CurveItem curve in this )
+ {
+ if ( curve == barItem )
+ return i;
+ else if ( curve is BarItem )
+ i++;
+ }
+
+ return -1;
+ }
+
+ #endregion
+
+ }
+}
+
+
diff --git a/ZedGraph/DataSourcePointList.cs b/ZedGraph/DataSourcePointList.cs
new file mode 100644
index 0000000..1e32847
--- /dev/null
+++ b/ZedGraph/DataSourcePointList.cs
@@ -0,0 +1,304 @@
+//============================================================================
+//DataSourcePointList Class
+//Copyright � 2006 John Champion, Jerry Vos
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Reflection;
+using System.Windows.Forms;
+using System.Data;
+
+namespace ZedGraph
+{
+ /// <summary>
+ ///
+ /// </summary>
+ /// <seealso cref="IPointList" />
+ /// <seealso cref="IPointListEdit" />
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.7 $ $Date: 2007-11-05 04:33:26 $ </version>
+ [Serializable]
+ public class DataSourcePointList : IPointList
+ {
+ private BindingSource _bindingSource;
+
+ //private object _dataSource = null;
+ private string _xDataMember = null;
+ private string _yDataMember = null;
+ private string _zDataMember = null;
+ private string _tagDataMember = null;
+
+ #region Properties
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="PointPair"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="PointPair"/> object to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object reference.</value>
+ public PointPair this[int index]
+ {
+ get
+ {
+ if ( index < 0 || index >= _bindingSource.Count )
+ throw new System.ArgumentOutOfRangeException( "Error: Index out of range" );
+
+ object row = _bindingSource[index];
+
+ double x = GetDouble( row, _xDataMember, index );
+ double y = GetDouble( row, _yDataMember, index );
+ double z = GetDouble( row, _zDataMember, index );
+ object tag = GetObject( row, _tagDataMember );
+
+ PointPair pt = new PointPair( x, y, z );
+ pt.Tag = tag;
+ return pt;
+ }
+ }
+
+ /// <summary>
+ /// gets the number of points available in the list
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ if ( _bindingSource != null )
+ return _bindingSource.Count;
+ else
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// The <see cref="BindingSource" /> object from which to get the bound data
+ /// </summary>
+ /// <remarks>
+ /// Typically, you set the <see cref="System.Windows.Forms.BindingSource.DataSource" />
+ /// property to a reference to your database, table or list object. The
+ /// <see cref="System.Windows.Forms.BindingSource.DataMember" /> property would be set
+ /// to the name of the datatable within the
+ /// <see cref="System.Windows.Forms.BindingSource.DataSource" />,
+ /// if applicable.</remarks>
+ public BindingSource BindingSource
+ {
+ get { return _bindingSource; }
+ }
+
+ /// <summary>
+ /// The table or list object from which to extract the data values.
+ /// </summary>
+ /// <remarks>
+ /// This property is just an alias for
+ /// <see cref="System.Windows.Forms.BindingSource.DataSource" />.
+ /// </remarks>
+ public object DataSource
+ {
+ get { return _bindingSource.DataSource; }
+ set { _bindingSource.DataSource = value; }
+ }
+
+ /// <summary>
+ /// The <see cref="string" /> name of the property or column from which to obtain the
+ /// X data values for the chart.
+ /// </summary>
+ /// <remarks>Set this to null leave the X data values set to <see cref="PointPairBase.Missing" />
+ /// </remarks>
+ public string XDataMember
+ {
+ get { return _xDataMember; }
+ set { _xDataMember = value; }
+ }
+
+ /// <summary>
+ /// The <see cref="string" /> name of the property or column from which to obtain the
+ /// Y data values for the chart.
+ /// </summary>
+ /// <remarks>Set this to null leave the Y data values set to <see cref="PointPairBase.Missing" />
+ /// </remarks>
+ public string YDataMember
+ {
+ get { return _yDataMember; }
+ set { _yDataMember = value; }
+ }
+
+ /// <summary>
+ /// The <see cref="string" /> name of the property or column from which to obtain the
+ /// Z data values for the chart.
+ /// </summary>
+ /// <remarks>Set this to null leave the Z data values set to <see cref="PointPairBase.Missing" />
+ /// </remarks>
+ public string ZDataMember
+ {
+ get { return _zDataMember; }
+ set { _zDataMember = value; }
+ }
+
+ /// <summary>
+ /// The <see cref="string" /> name of the property or column from which to obtain the
+ /// tag values for the chart.
+ /// </summary>
+ /// <remarks>Set this to null leave the tag values set to null. If this references string
+ /// data, then the tags may be used as tooltips using the
+ /// <see cref="ZedGraphControl.IsShowPointValues" /> option.
+ /// </remarks>
+ public string TagDataMember
+ {
+ get { return _tagDataMember; }
+ set { _tagDataMember = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public DataSourcePointList()
+ {
+ _bindingSource = new BindingSource();
+ _xDataMember = string.Empty;
+ _yDataMember = string.Empty;
+ _zDataMember = string.Empty;
+ _tagDataMember = string.Empty;
+ }
+
+ /// <summary>
+ /// Constructor to initialize the DataSourcePointList from an
+ /// existing <see cref="DataSourcePointList" />
+ /// </summary>
+ public DataSourcePointList( DataSourcePointList rhs )
+ : this()
+ {
+ _bindingSource.DataSource = rhs._bindingSource.DataSource;
+ if ( rhs._xDataMember != null )
+ _xDataMember = (string)rhs._xDataMember.Clone();
+ if ( rhs._yDataMember != null )
+ _yDataMember = (string)rhs._yDataMember.Clone();
+ if ( rhs._zDataMember != null )
+ _zDataMember = (string)rhs._zDataMember.Clone();
+ if ( rhs._tagDataMember != null )
+ _tagDataMember = (string)rhs._tagDataMember.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public DataSourcePointList Clone()
+ {
+ return new DataSourcePointList( this );
+ }
+
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Extract a double value from the specified table row or data object with the
+ /// specified column name.
+ /// </summary>
+ /// <param name="row">The data object from which to extract the value</param>
+ /// <param name="dataMember">The property name or column name of the value
+ /// to be extracted</param>
+ /// <param name="index">The zero-based index of the point to be extracted.
+ /// </param>
+ private double GetDouble( object row, string dataMember, int index )
+ {
+ if ( dataMember == null || dataMember == string.Empty )
+ return index + 1;
+
+ //Type myType = row.GetType();
+ DataRowView drv = row as DataRowView;
+ PropertyInfo pInfo = null;
+ if ( drv == null )
+ pInfo = row.GetType().GetProperty( dataMember );
+
+ object val = null;
+
+ if ( pInfo != null )
+ val = pInfo.GetValue( row, null );
+ else if ( drv != null )
+ val = drv[dataMember];
+ else if ( pInfo == null )
+ throw new System.Exception( "Can't find DataMember '" + dataMember + "' in DataSource" );
+
+ // if ( val == null )
+ // throw new System.Exception( "Can't find DataMember '" + dataMember + "' in DataSource" );
+
+ double x;
+ if ( val == null || val == DBNull.Value )
+ x = PointPair.Missing;
+ else if ( val.GetType() == typeof( DateTime ) )
+ x = ( (DateTime)val ).ToOADate();
+ else if ( val.GetType() == typeof( string ) )
+ x = index + 1;
+ else
+ x = Convert.ToDouble( val );
+
+ return x;
+ }
+
+ /// <summary>
+ /// Extract an object from the specified table row or data object with the
+ /// specified column name.
+ /// </summary>
+ /// <param name="row">The data object from which to extract the object</param>
+ /// <param name="dataMember">The property name or column name of the object
+ /// to be extracted</param>
+ private object GetObject( object row, string dataMember )
+ {
+ if ( dataMember == null || dataMember == string.Empty )
+ return null;
+
+ PropertyInfo pInfo = row.GetType().GetProperty( dataMember );
+ DataRowView drv = row as DataRowView;
+
+ object val = null;
+
+ if ( pInfo != null )
+ val = pInfo.GetValue( row, null );
+ else if ( drv != null )
+ val = drv[dataMember];
+
+ if ( val == null )
+ throw new System.Exception( "Can't find DataMember '" + dataMember + "' in DataSource" );
+
+ return val;
+ }
+
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/DateAsOrdinalScale.cs b/ZedGraph/DateAsOrdinalScale.cs
new file mode 100644
index 0000000..a603878
--- /dev/null
+++ b/ZedGraph/DateAsOrdinalScale.cs
@@ -0,0 +1,338 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The DateAsOrdinalScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.DateAsOrdinal" />.
+ /// </summary>
+ /// <remarks>DateAsOrdinalScale is an ordinal axis that will have labels formatted with dates from the
+ /// actual data values of the first <see cref="CurveItem" /> in the <see cref="CurveList" />.
+ /// Although the tics are labeled with real data values, the actual points will be
+ /// evenly-spaced in spite of the data values. For example, if the X values of the first curve
+ /// are 1, 5, and 100, then the tic labels will show 1, 5, and 100, but they will be equal
+ /// distance from each other.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.13 $ $Date: 2007-11-28 02:38:22 $ </version>
+ [Serializable]
+ class DateAsOrdinalScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public DateAsOrdinalScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="DateAsOrdinalScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="DateAsOrdinalScale" /></param>
+ public DateAsOrdinalScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new DateAsOrdinalScale( this, owner );
+ }
+
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Return the <see cref="AxisType" /> for this <see cref="Scale" />, which is
+ /// <see cref="AxisType.DateAsOrdinal" />.
+ /// </summary>
+ public override AxisType Type
+ {
+ get { return AxisType.DateAsOrdinal; }
+ }
+
+ /// <summary>
+ /// Gets or sets the minimum value for this scale.
+ /// </summary>
+ /// <remarks>
+ /// The set property is specifically adapted for <see cref="AxisType.DateAsOrdinal" /> scales,
+ /// in that it automatically limits the value to the range of valid dates for the
+ /// <see cref="XDate" /> struct.
+ /// </remarks>
+ public override double Min
+ {
+ get { return _min; }
+ set { _min = XDate.MakeValidDate( value ); _minAuto = false; }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum value for this scale.
+ /// </summary>
+ /// <remarks>
+ /// The set property is specifically adapted for <see cref="AxisType.DateAsOrdinal" /> scales,
+ /// in that it automatically limits the value to the range of valid dates for the
+ /// <see cref="XDate" /> struct.
+ /// </remarks>
+ public override double Max
+ {
+ get { return _max; }
+ set { _max = XDate.MakeValidDate( value ); _maxAuto = false; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Select a reasonable ordinal axis scale given a range of data values, with the expectation that
+ /// dates will be displayed.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.DateAsOrdinal"/> type axes, and it
+ /// is called by the general <see cref="PickScale"/> method. For this type,
+ /// the first curve is the "master", which contains the dates to be applied.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="PickScale"/>
+ /// <seealso cref="AxisType.Ordinal"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+/* // First, get the date ranges from the first curve in the list
+ double xMin; // = Double.MaxValue;
+ double xMax; // = Double.MinValue;
+ double yMin; // = Double.MaxValue;
+ double yMax; // = Double.MinValue;
+ double range = 1;
+
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ if ( ( _ownerAxis is Y2Axis && curve.IsY2Axis ) ||
+ ( _ownerAxis is YAxis && !curve.IsY2Axis ) ||
+ ( _ownerAxis is X2Axis && curve.IsX2Axis ) ||
+ ( _ownerAxis is XAxis && !curve.IsX2Axis ) )
+ {
+ curve.GetRange( out xMin, out xMax, out yMin, out yMax, false, pane.IsBoundedRanges, pane );
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ range = xMax - xMin;
+ else
+ range = yMax - yMin;
+ }
+ }
+*/
+ // Set the DateFormat by calling CalcDateStepSize
+ // DateScale.CalcDateStepSize( range, Default.TargetXSteps, this );
+ SetDateFormat( pane );
+
+ // Now, set the axis range based on a ordinal scale
+ base.PickScale( pane, g, scaleFactor );
+ OrdinalScale.PickScale( pane, g, scaleFactor, this );
+ }
+
+ internal void SetDateFormat( GraphPane pane )
+ {
+ if ( _formatAuto )
+ {
+ double range = 10;
+
+ if ( pane.CurveList.Count > 0 && pane.CurveList[0].Points.Count > 1 )
+ {
+ double val1, val2;
+
+ PointPair pt1 = pane.CurveList[0].Points[0];
+ PointPair pt2 = pane.CurveList[0].Points[pane.CurveList[0].Points.Count - 1];
+ int p1 = 1;
+ int p2 = pane.CurveList[0].Points.Count;
+ if ( pane.IsBoundedRanges )
+ {
+ p1 = (int) Math.Floor( _ownerAxis.Scale.Min );
+ p2 = (int) Math.Ceiling( _ownerAxis.Scale.Max );
+ p1 = Math.Min( Math.Max( p1, 1 ), pane.CurveList[0].Points.Count );
+ p2 = Math.Min( Math.Max( p2, 1 ), pane.CurveList[0].Points.Count );
+ if ( p2 > p1 )
+ {
+ pt1 = pane.CurveList[0].Points[p1-1];
+ pt2 = pane.CurveList[0].Points[p2-1];
+ }
+ }
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ {
+ val1 = pt1.X;
+ val2 = pt2.X;
+ }
+ else
+ {
+ val1 = pt1.Y;
+ val2 = pt2.Y;
+ }
+
+ if ( val1 != PointPair.Missing &&
+ val2 != PointPair.Missing &&
+ !Double.IsNaN( val1 ) &&
+ !Double.IsNaN( val2 ) &&
+ !Double.IsInfinity( val1 ) &&
+ !Double.IsInfinity( val2 ) &&
+ Math.Abs( val2 - val1 ) > 1e-10 )
+ range = Math.Abs( val2 - val1 );
+ }
+
+ if ( range > Default.RangeYearYear )
+ _format = Default.FormatYearYear;
+ else if ( range > Default.RangeYearMonth )
+ _format = Default.FormatYearMonth;
+ else if ( range > Default.RangeMonthMonth )
+ _format = Default.FormatMonthMonth;
+ else if ( range > Default.RangeDayDay )
+ _format = Default.FormatDayDay;
+ else if ( range > Default.RangeDayHour )
+ _format = Default.FormatDayHour;
+ else if ( range > Default.RangeHourHour )
+ _format = Default.FormatHourHour;
+ else if ( range > Default.RangeHourMinute )
+ _format = Default.FormatHourMinute;
+ else if ( range > Default.RangeMinuteMinute )
+ _format = Default.FormatMinuteMinute;
+ else if ( range > Default.RangeMinuteSecond )
+ _format = Default.FormatMinuteSecond;
+ else if ( range > Default.RangeSecondSecond )
+ _format = Default.FormatSecondSecond;
+ else // MilliSecond
+ _format = Default.FormatMillisecond;
+ }
+ }
+
+ /// <summary>
+ /// Make a value label for an <see cref="AxisType.DateAsOrdinal" /> <see cref="Axis" />.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log
+ /// (<see cref="Scale.IsLog"/>)
+ /// and text (<see cref="Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ override internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ double val;
+
+ int tmpIndex = (int) dVal - 1;
+
+ if ( pane.CurveList.Count > 0 && pane.CurveList[0].Points.Count > tmpIndex )
+ {
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ val = pane.CurveList[0].Points[tmpIndex].X;
+ else
+ val = pane.CurveList[0].Points[tmpIndex].Y;
+ return XDate.ToString( val, _format );
+ }
+ else
+ return string.Empty;
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected DateAsOrdinalScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/DateScale.cs b/ZedGraph/DateScale.cs
new file mode 100644
index 0000000..71c1c2d
--- /dev/null
+++ b/ZedGraph/DateScale.cs
@@ -0,0 +1,946 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The DateScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.Date" />.
+ /// </summary>
+ /// <remarks>
+ /// DateScale is a cartesian axis with calendar dates or times. The actual data values should
+ /// be created with the <see cref="XDate" /> type, which is directly translatable to a
+ /// <see cref="System.Double" /> type for storage in the point value arrays.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.15 $ $Date: 2007-09-19 06:41:56 $ </version>
+ [Serializable]
+ class DateScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public DateScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="DateScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="DateScale" /></param>
+ public DateScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new DateScale( this, owner );
+ }
+
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Return the <see cref="AxisType" /> for this <see cref="Scale" />, which is
+ /// <see cref="AxisType.Date" />.
+ /// </summary>
+ public override AxisType Type
+ {
+ get { return AxisType.Date; }
+ }
+
+ /// <summary>
+ /// Gets or sets the minimum value for this scale.
+ /// </summary>
+ /// <remarks>
+ /// The set property is specifically adapted for <see cref="AxisType.Date" /> scales,
+ /// in that it automatically limits the value to the range of valid dates for the
+ /// <see cref="XDate" /> struct.
+ /// </remarks>
+ public override double Min
+ {
+ get { return _min; }
+ set { _min = XDate.MakeValidDate( value ); _minAuto = false; }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum value for this scale.
+ /// </summary>
+ /// <remarks>
+ /// The set property is specifically adapted for <see cref="AxisType.Date" /> scales,
+ /// in that it automatically limits the value to the range of valid dates for the
+ /// <see cref="XDate" /> struct.
+ /// </remarks>
+ public override double Max
+ {
+ get { return _max; }
+ set { _max = XDate.MakeValidDate( value ); _maxAuto = false; }
+ }
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Determine the value for any major tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double)
+ /// </param>
+ /// <param name="tic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified major tic value (floating point double).
+ /// </returns>
+ override internal double CalcMajorTicValue( double baseVal, double tic )
+ {
+ XDate xDate = new XDate( baseVal );
+
+ switch ( _majorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ xDate.AddYears( tic * _majorStep );
+ break;
+ case DateUnit.Month:
+ xDate.AddMonths( tic * _majorStep );
+ break;
+ case DateUnit.Day:
+ xDate.AddDays( tic * _majorStep );
+ break;
+ case DateUnit.Hour:
+ xDate.AddHours( tic * _majorStep );
+ break;
+ case DateUnit.Minute:
+ xDate.AddMinutes( tic * _majorStep );
+ break;
+ case DateUnit.Second:
+ xDate.AddSeconds( tic * _majorStep );
+ break;
+ case DateUnit.Millisecond:
+ xDate.AddMilliseconds( tic * _majorStep );
+ break;
+ }
+
+ return xDate.XLDate;
+ }
+
+ /// <summary>
+ /// Determine the value for any minor tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double). This tic value is the base
+ /// reference for all tics (including minor ones).
+ /// </param>
+ /// <param name="iTic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified minor tic value (floating point double).
+ /// </returns>
+ override internal double CalcMinorTicValue( double baseVal, int iTic )
+ {
+ XDate xDate = new XDate( baseVal );
+
+ switch ( _minorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ xDate.AddYears( (double) iTic * _minorStep );
+ break;
+ case DateUnit.Month:
+ xDate.AddMonths( (double) iTic * _minorStep );
+ break;
+ case DateUnit.Day:
+ xDate.AddDays( (double) iTic * _minorStep );
+ break;
+ case DateUnit.Hour:
+ xDate.AddHours( (double) iTic * _minorStep );
+ break;
+ case DateUnit.Minute:
+ xDate.AddMinutes( (double) iTic * _minorStep );
+ break;
+ case DateUnit.Second:
+ xDate.AddSeconds( (double) iTic * _minorStep );
+ break;
+ }
+
+ return xDate.XLDate;
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first minor tic mark
+ /// </summary>
+ /// <param name="baseVal">
+ /// The value of the first major tic for the axis.
+ /// </param>
+ /// <returns>
+ /// The ordinal position of the first minor tic, relative to the first major tic.
+ /// This value can be negative (e.g., -3 means the first minor tic is 3 minor step
+ /// increments before the first major tic.
+ /// </returns>
+ override internal int CalcMinorStart( double baseVal )
+ {
+ switch ( _minorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ return (int) ( ( _min - baseVal ) / ( 365.0 * _minorStep ) );
+ case DateUnit.Month:
+ return (int) ( ( _min - baseVal ) / ( 28.0 * _minorStep ) );
+ case DateUnit.Day:
+ return (int) ( ( _min - baseVal ) / _minorStep );
+ case DateUnit.Hour:
+ return (int) ( ( _min - baseVal ) * XDate.HoursPerDay / _minorStep );
+ case DateUnit.Minute:
+ return (int) ( ( _min - baseVal ) * XDate.MinutesPerDay / _minorStep );
+ case DateUnit.Second:
+ return (int) ( ( _min - baseVal ) * XDate.SecondsPerDay / _minorStep );
+ }
+ }
+
+ /// <summary>
+ /// Determine the value for the first major tic.
+ /// </summary>
+ /// <remarks>
+ /// This is done by finding the first possible value that is an integral multiple of
+ /// the step size, taking into account the date/time units if appropriate.
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <returns>
+ /// First major tic value (floating point double).
+ /// </returns>
+ override internal double CalcBaseTic()
+ {
+ if ( _baseTic != PointPair.Missing )
+ return _baseTic;
+ else
+ {
+ int year, month, day, hour, minute, second, millisecond;
+ XDate.XLDateToCalendarDate( _min, out year, out month, out day, out hour, out minute,
+ out second, out millisecond );
+ switch ( _majorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ month = 1; day = 1; hour = 0; minute = 0; second = 0; millisecond = 0;
+ break;
+ case DateUnit.Month:
+ day = 1; hour = 0; minute = 0; second = 0; millisecond = 0;
+ break;
+ case DateUnit.Day:
+ hour = 0; minute = 0; second = 0; millisecond = 0;
+ break;
+ case DateUnit.Hour:
+ minute = 0; second = 0; millisecond = 0;
+ break;
+ case DateUnit.Minute:
+ second = 0; millisecond = 0;
+ break;
+ case DateUnit.Second:
+ millisecond = 0;
+ break;
+ case DateUnit.Millisecond:
+ break;
+
+ }
+
+ double xlDate = XDate.CalendarDateToXLDate( year, month, day, hour, minute, second, millisecond );
+ if ( xlDate < _min )
+ {
+ switch ( _majorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ year++;
+ break;
+ case DateUnit.Month:
+ month++;
+ break;
+ case DateUnit.Day:
+ day++;
+ break;
+ case DateUnit.Hour:
+ hour++;
+ break;
+ case DateUnit.Minute:
+ minute++;
+ break;
+ case DateUnit.Second:
+ second++;
+ break;
+ case DateUnit.Millisecond:
+ millisecond++;
+ break;
+
+ }
+
+ xlDate = XDate.CalendarDateToXLDate( year, month, day, hour, minute, second, millisecond );
+ }
+
+ return xlDate;
+ }
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first and last major axis label.
+ /// </summary>
+ /// <returns>
+ /// This is the total number of major tics for this axis.
+ /// </returns>
+ override internal int CalcNumTics()
+ {
+ int nTics = 1;
+
+ int year1, year2, month1, month2, day1, day2, hour1, hour2, minute1, minute2;
+ int second1, second2, millisecond1, millisecond2;
+
+ XDate.XLDateToCalendarDate( _min, out year1, out month1, out day1,
+ out hour1, out minute1, out second1, out millisecond1 );
+ XDate.XLDateToCalendarDate( _max, out year2, out month2, out day2,
+ out hour2, out minute2, out second2, out millisecond2 );
+
+ switch ( _majorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ nTics = (int) ( ( year2 - year1 ) / _majorStep + 1.001 );
+ break;
+ case DateUnit.Month:
+ nTics = (int) ( ( month2 - month1 + 12.0 * ( year2 - year1 ) ) / _majorStep + 1.001 );
+ break;
+ case DateUnit.Day:
+ nTics = (int) ( ( _max - _min ) / _majorStep + 1.001 );
+ break;
+ case DateUnit.Hour:
+ nTics = (int) ( ( _max - _min ) / ( _majorStep / XDate.HoursPerDay ) + 1.001 );
+ break;
+ case DateUnit.Minute:
+ nTics = (int) ( ( _max - _min ) / ( _majorStep / XDate.MinutesPerDay ) + 1.001 );
+ break;
+ case DateUnit.Second:
+ nTics = (int)( ( _max - _min ) / ( _majorStep / XDate.SecondsPerDay ) + 1.001 );
+ break;
+ case DateUnit.Millisecond:
+ nTics = (int)( ( _max - _min ) / ( _majorStep / XDate.MillisecondsPerDay ) + 1.001 );
+ break;
+ }
+
+ if ( nTics < 1 )
+ nTics = 1;
+ else if ( nTics > 1000 )
+ nTics = 1000;
+
+ return nTics;
+ }
+
+ /// <summary>
+ /// Select a reasonable date-time axis scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.Date"/> type axes, and it
+ /// is called by the general <see cref="PickScale"/> method. The scale range is chosen
+ /// based on increments of 1, 2, or 5 (because they are even divisors of 10).
+ /// Note that the <see cref="Scale.MajorStep"/> property setting can have multiple unit
+ /// types (<see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit" />),
+ /// but the <see cref="Scale.Min"/> and
+ /// <see cref="Scale.Max"/> units are always days (<see cref="XDate"/>). This
+ /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/> autorange settings.
+ /// In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/>
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values. The basic default for
+ /// scale selection is defined with
+ /// <see cref="Scale.Default.TargetXSteps"/> and <see cref="Scale.Default.TargetYSteps"/>
+ /// from the <see cref="Scale.Default"/> default class.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="Scale.PickScale"/>
+ /// <seealso cref="AxisType.Date"/>
+ /// <seealso cref="Scale.MajorUnit"/>
+ /// <seealso cref="Scale.MinorUnit"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ // Test for trivial condition of range = 0 and pick a suitable default
+ if ( _max - _min < 1.0e-20 )
+ {
+ if ( _maxAuto )
+ _max = _max + 0.2 * ( _max == 0 ? 1.0 : Math.Abs( _max ) );
+ if ( _minAuto )
+ _min = _min - 0.2 * ( _min == 0 ? 1.0 : Math.Abs( _min ) );
+ }
+
+ double targetSteps = ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ?
+ Default.TargetXSteps : Default.TargetYSteps;
+
+ // Calculate the step size based on target steps
+ double tempStep = CalcDateStepSize( _max - _min, targetSteps );
+
+ // Calculate the new step size
+ if ( _majorStepAuto )
+ {
+ _majorStep = tempStep;
+
+ if ( _isPreventLabelOverlap )
+ {
+ // Calculate the maximum number of labels
+ double maxLabels = (double) this.CalcMaxLabels( g, pane, scaleFactor );
+
+ if ( maxLabels < this.CalcNumTics() )
+ _majorStep = CalcDateStepSize( _max - _min, maxLabels );
+ }
+ }
+
+ // Calculate the scale minimum
+ if ( _minAuto )
+ _min = CalcEvenStepDate( _min, -1 );
+
+ // Calculate the scale maximum
+ if ( _maxAuto )
+ _max = CalcEvenStepDate( _max, 1 );
+
+ _mag = 0; // Never use a magnitude shift for date scales
+ //this.numDec = 0; // The number of decimal places to display is not used
+
+ }
+
+ /// <summary>
+ /// Calculate a step size for a <see cref="AxisType.Date"/> scale.
+ /// This method is used by <see cref="PickScale"/>.
+ /// </summary>
+ /// <param name="range">The range of data in units of days</param>
+ /// <param name="targetSteps">The desired "typical" number of steps
+ /// to divide the range into</param>
+ /// <returns>The calculated step size for the specified data range. Also
+ /// calculates and sets the values for <see cref="Scale.MajorUnit"/>,
+ /// <see cref="Scale.MinorUnit"/>, <see cref="Scale.MinorStep"/>, and
+ /// <see cref="Scale.Format"/></returns>
+ protected double CalcDateStepSize( double range, double targetSteps )
+ {
+ return CalcDateStepSize( range, targetSteps, this );
+ }
+
+ /// <summary>
+ /// Calculate a step size for a <see cref="AxisType.Date"/> scale.
+ /// This method is used by <see cref="PickScale"/>.
+ /// </summary>
+ /// <param name="range">The range of data in units of days</param>
+ /// <param name="targetSteps">The desired "typical" number of steps
+ /// to divide the range into</param>
+ /// <param name="scale">
+ /// The <see cref="Scale" /> object on which to calculate the Date step size.</param>
+ /// <returns>The calculated step size for the specified data range. Also
+ /// calculates and sets the values for <see cref="Scale.MajorUnit"/>,
+ /// <see cref="Scale.MinorUnit"/>, <see cref="Scale.MinorStep"/>, and
+ /// <see cref="Scale.Format"/></returns>
+ internal static double CalcDateStepSize( double range, double targetSteps, Scale scale )
+ {
+ // Calculate an initial guess at step size
+ double tempStep = range / targetSteps;
+
+ if ( range > Default.RangeYearYear )
+ {
+ scale._majorUnit = DateUnit.Year;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatYearYear;
+
+ tempStep = Math.Ceiling( tempStep / 365.0 );
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Year;
+ if ( tempStep == 1.0 )
+ scale._minorStep = 0.25;
+ else
+ scale._minorStep = Scale.CalcStepSize( tempStep, targetSteps );
+ }
+ }
+ else if ( range > Default.RangeYearMonth )
+ {
+ scale._majorUnit = DateUnit.Year;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatYearMonth;
+ tempStep = Math.Ceiling( tempStep / 365.0 );
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Month;
+ // Calculate the minor steps to give an estimated 4 steps
+ // per major step.
+ scale._minorStep = Math.Ceiling( range / ( targetSteps * 3 ) / 30.0 );
+ // make sure the minorStep is 1, 2, 3, 6, or 12 months
+ if ( scale._minorStep > 6 )
+ scale._minorStep = 12;
+ else if ( scale._minorStep > 3 )
+ scale._minorStep = 6;
+ }
+ }
+ else if ( range > Default.RangeMonthMonth )
+ {
+ scale._majorUnit = DateUnit.Month;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatMonthMonth;
+ tempStep = Math.Ceiling( tempStep / 30.0 );
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Month;
+ scale._minorStep = tempStep * 0.25;
+ }
+ }
+ else if ( range > Default.RangeDayDay )
+ {
+ scale._majorUnit = DateUnit.Day;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatDayDay;
+ tempStep = Math.Ceiling( tempStep );
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Day;
+ scale._minorStep = tempStep * 0.25;
+ // make sure the minorStep is 1, 2, 3, 6, or 12 hours
+ }
+ }
+ else if ( range > Default.RangeDayHour )
+ {
+ scale._majorUnit = DateUnit.Day;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatDayHour;
+ tempStep = Math.Ceiling( tempStep );
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Hour;
+ // Calculate the minor steps to give an estimated 4 steps
+ // per major step.
+ scale._minorStep = Math.Ceiling( range / ( targetSteps * 3 ) * XDate.HoursPerDay );
+ // make sure the minorStep is 1, 2, 3, 6, or 12 hours
+ if ( scale._minorStep > 6 )
+ scale._minorStep = 12;
+ else if ( scale._minorStep > 3 )
+ scale._minorStep = 6;
+ else
+ scale._minorStep = 1;
+ }
+ }
+ else if ( range > Default.RangeHourHour )
+ {
+ scale._majorUnit = DateUnit.Hour;
+ tempStep = Math.Ceiling( tempStep * XDate.HoursPerDay );
+ if ( scale._formatAuto )
+ scale._format = Default.FormatHourHour;
+
+ if ( tempStep > 12.0 )
+ tempStep = 24.0;
+ else if ( tempStep > 6.0 )
+ tempStep = 12.0;
+ else if ( tempStep > 2.0 )
+ tempStep = 6.0;
+ else if ( tempStep > 1.0 )
+ tempStep = 2.0;
+ else
+ tempStep = 1.0;
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Hour;
+ if ( tempStep <= 1.0 )
+ scale._minorStep = 0.25;
+ else if ( tempStep <= 6.0 )
+ scale._minorStep = 1.0;
+ else if ( tempStep <= 12.0 )
+ scale._minorStep = 2.0;
+ else
+ scale._minorStep = 4.0;
+ }
+ }
+ else if ( range > Default.RangeHourMinute )
+ {
+ scale._majorUnit = DateUnit.Hour;
+ tempStep = Math.Ceiling( tempStep * XDate.HoursPerDay );
+
+ if ( scale._formatAuto )
+ scale._format = Default.FormatHourMinute;
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Minute;
+ // Calculate the minor steps to give an estimated 4 steps
+ // per major step.
+ scale._minorStep = Math.Ceiling( range / ( targetSteps * 3 ) * XDate.MinutesPerDay );
+ // make sure the minorStep is 1, 5, 15, or 30 minutes
+ if ( scale._minorStep > 15.0 )
+ scale._minorStep = 30.0;
+ else if ( scale._minorStep > 5.0 )
+ scale._minorStep = 15.0;
+ else if ( scale._minorStep > 1.0 )
+ scale._minorStep = 5.0;
+ else
+ scale._minorStep = 1.0;
+ }
+ }
+ else if ( range > Default.RangeMinuteMinute )
+ {
+ scale._majorUnit = DateUnit.Minute;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatMinuteMinute;
+
+ tempStep = Math.Ceiling( tempStep * XDate.MinutesPerDay );
+ // make sure the minute step size is 1, 5, 15, or 30 minutes
+ if ( tempStep > 15.0 )
+ tempStep = 30.0;
+ else if ( tempStep > 5.0 )
+ tempStep = 15.0;
+ else if ( tempStep > 1.0 )
+ tempStep = 5.0;
+ else
+ tempStep = 1.0;
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Minute;
+ if ( tempStep <= 1.0 )
+ scale._minorStep = 0.25;
+ else if ( tempStep <= 5.0 )
+ scale._minorStep = 1.0;
+ else
+ scale._minorStep = 5.0;
+ }
+ }
+ else if ( range > Default.RangeMinuteSecond )
+ {
+ scale._majorUnit = DateUnit.Minute;
+ tempStep = Math.Ceiling( tempStep * XDate.MinutesPerDay );
+
+ if ( scale._formatAuto )
+ scale._format = Default.FormatMinuteSecond;
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Second;
+ // Calculate the minor steps to give an estimated 4 steps
+ // per major step.
+ scale._minorStep = Math.Ceiling( range / ( targetSteps * 3 ) * XDate.SecondsPerDay );
+ // make sure the minorStep is 1, 5, 15, or 30 seconds
+ if ( scale._minorStep > 15.0 )
+ scale._minorStep = 30.0;
+ else if ( scale._minorStep > 5.0 )
+ scale._minorStep = 15.0;
+ else if ( scale._minorStep > 1.0 )
+ scale._minorStep = 5.0;
+ else
+ scale._minorStep = 1.0;
+ }
+ }
+ else if ( range > Default.RangeSecondSecond ) // SecondSecond
+ {
+ scale._majorUnit = DateUnit.Second;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatSecondSecond;
+
+ tempStep = Math.Ceiling( tempStep * XDate.SecondsPerDay );
+ // make sure the second step size is 1, 5, 15, or 30 seconds
+ if ( tempStep > 15.0 )
+ tempStep = 30.0;
+ else if ( tempStep > 5.0 )
+ tempStep = 15.0;
+ else if ( tempStep > 1.0 )
+ tempStep = 5.0;
+ else
+ tempStep = 1.0;
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorUnit = DateUnit.Second;
+ if ( tempStep <= 1.0 )
+ scale._minorStep = 0.25;
+ else if ( tempStep <= 5.0 )
+ scale._minorStep = 1.0;
+ else
+ scale._minorStep = 5.0;
+ }
+ }
+ else // MilliSecond
+ {
+ scale._majorUnit = DateUnit.Millisecond;
+ if ( scale._formatAuto )
+ scale._format = Default.FormatMillisecond;
+
+ tempStep = CalcStepSize( range * XDate.MillisecondsPerDay, Default.TargetXSteps );
+
+ if ( scale._minorStepAuto )
+ {
+ scale._minorStep = CalcStepSize( tempStep,
+ ( scale._ownerAxis is XAxis || scale._ownerAxis is X2Axis ) ?
+ Default.TargetMinorXSteps : Default.TargetMinorYSteps );
+ scale._minorUnit = DateUnit.Millisecond;
+ }
+ }
+
+ return tempStep;
+ }
+
+ /// <summary>
+ /// Calculate a date that is close to the specified date and an
+ /// even multiple of the selected
+ /// <see cref="Scale.MajorUnit"/> for a <see cref="AxisType.Date"/> scale.
+ /// This method is used by <see cref="PickScale"/>.
+ /// </summary>
+ /// <param name="date">The date which the calculation should be close to</param>
+ /// <param name="direction">The desired direction for the date to take.
+ /// 1 indicates the result date should be greater than the specified
+ /// date parameter. -1 indicates the other direction.</param>
+ /// <returns>The calculated date</returns>
+ protected double CalcEvenStepDate( double date, int direction )
+ {
+ int year, month, day, hour, minute, second, millisecond;
+
+ XDate.XLDateToCalendarDate( date, out year, out month, out day,
+ out hour, out minute, out second, out millisecond );
+
+ // If the direction is -1, then it is sufficient to go to the beginning of
+ // the current time period, .e.g., for 15-May-95, and monthly steps, we
+ // can just back up to 1-May-95
+ if ( direction < 0 )
+ direction = 0;
+
+ switch ( _majorUnit )
+ {
+ case DateUnit.Year:
+ default:
+ // If the date is already an exact year, then don't step to the next year
+ if ( direction == 1 && month == 1 && day == 1 && hour == 0
+ && minute == 0 && second == 0 )
+ return date;
+ else
+ return XDate.CalendarDateToXLDate( year + direction, 1, 1,
+ 0, 0, 0 );
+ case DateUnit.Month:
+ // If the date is already an exact month, then don't step to the next month
+ if ( direction == 1 && day == 1 && hour == 0
+ && minute == 0 && second == 0 )
+ return date;
+ else
+ return XDate.CalendarDateToXLDate( year, month + direction, 1,
+ 0, 0, 0 );
+ case DateUnit.Day:
+ // If the date is already an exact Day, then don't step to the next day
+ if ( direction == 1 && hour == 0 && minute == 0 && second == 0 )
+ return date;
+ else
+ return XDate.CalendarDateToXLDate( year, month,
+ day + direction, 0, 0, 0 );
+ case DateUnit.Hour:
+ // If the date is already an exact hour, then don't step to the next hour
+ if ( direction == 1 && minute == 0 && second == 0 )
+ return date;
+ else
+ return XDate.CalendarDateToXLDate( year, month, day,
+ hour + direction, 0, 0 );
+ case DateUnit.Minute:
+ // If the date is already an exact minute, then don't step to the next minute
+ if ( direction == 1 && second == 0 )
+ return date;
+ else
+ return XDate.CalendarDateToXLDate( year, month, day, hour,
+ minute + direction, 0 );
+ case DateUnit.Second:
+ return XDate.CalendarDateToXLDate( year, month, day, hour,
+ minute, second + direction );
+
+ case DateUnit.Millisecond:
+ return XDate.CalendarDateToXLDate( year, month, day, hour,
+ minute, second, millisecond + direction );
+
+ }
+ }
+
+ /// <summary>
+ /// Make a value label for an <see cref="AxisType.Date" /> <see cref="Axis" />.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="Scale.IsLog"/>)
+ /// and text (<see cref="Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ override internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ return XDate.ToString( dVal, _format );
+ }
+
+ /// <summary>
+ /// Gets the major unit multiplier for this scale type, if any.
+ /// </summary>
+ /// <remarks>The major unit multiplier will correct the units of
+ /// <see cref="Scale.MajorStep" /> to match the units of <see cref="Scale.Min" />
+ /// and <see cref="Scale.Max" />. This reflects the setting of
+ /// <see cref="Scale.MajorUnit" />.
+ /// </remarks>
+ override internal double MajorUnitMultiplier
+ {
+ get { return GetUnitMultiple( _majorUnit ); }
+ }
+
+ /// <summary>
+ /// Gets the minor unit multiplier for this scale type, if any.
+ /// </summary>
+ /// <remarks>The minor unit multiplier will correct the units of
+ /// <see cref="Scale.MinorStep" /> to match the units of <see cref="Scale.Min" />
+ /// and <see cref="Scale.Max" />. This reflects the setting of
+ /// <see cref="Scale.MinorUnit" />.
+ /// </remarks>
+ override internal double MinorUnitMultiplier
+ {
+ get { return GetUnitMultiple( _minorUnit ); }
+ }
+
+ /// <summary>
+ /// Internal routine to calculate a multiplier to the selected unit back to days.
+ /// </summary>
+ /// <param name="unit">The unit type for which the multiplier is to be
+ /// calculated</param>
+ /// <returns>
+ /// This is ratio of days/selected unit
+ /// </returns>
+ private double GetUnitMultiple( DateUnit unit )
+ {
+ switch ( unit )
+ {
+ case DateUnit.Year:
+ default:
+ return 365.0;
+ case DateUnit.Month:
+ return 30.0;
+ case DateUnit.Day:
+ return 1.0;
+ case DateUnit.Hour:
+ return 1.0 / XDate.HoursPerDay;
+ case DateUnit.Minute:
+ return 1.0 / XDate.MinutesPerDay;
+ case DateUnit.Second:
+ return 1.0 / XDate.SecondsPerDay;
+ case DateUnit.Millisecond:
+ return 1.0 / XDate.MillisecondsPerDay;
+ }
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected DateScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/DynFilteredPointList.cs b/ZedGraph/DynFilteredPointList.cs
new file mode 100644
index 0000000..f9ef3b7
--- /dev/null
+++ b/ZedGraph/DynFilteredPointList.cs
@@ -0,0 +1,607 @@
+//============================================================================
+//DynFilteredPointList class
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System;
+using System.Collections.Generic;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An example of an <see cref="IPointList" /> implementation that stores large datasets, and
+ /// selectively filters the output data depending on the displayed range.
+ /// </summary>
+ /// <remarks>
+ /// This class will refilter the data points each time <see cref="FilterData" /> is called.
+ /// The data is filtered down to a maximum of <see cref="MaxPts" /> points,
+ /// within the data bounds of a minimum and maximum data range.
+ /// If the property <see cref="IsApplyHighLowLogic"/> is set to true, the data is
+ /// filtered as follows:
+ /// The data is divided into segments of equal width in the X axis with each
+ /// segment containing 4 points, the start, {minimum and maximum} and end.
+ /// Each segment could be a pixel for example.
+ /// If <see cref="IsApplyHighLowLogic"/> is set to false, the algorithm simply skips
+ /// points to achieve the desired total number of points.
+ /// Input arrays are assumed to be monotonically increasing in X,
+ /// but not necessarily equally spaced in X.
+ /// </remarks>
+ /// <seealso cref="PointPairList" />
+ /// <seealso cref="BasicArrayPointList" />
+ /// <seealso cref="IPointList" />
+ /// <seealso cref="IPointListEdit" />
+ ///
+ /// <author> ingineer based on John Champion's FilteredPointList class</author>
+ /// <version> $Revision: $ $Date: $ </version>
+ [Serializable]
+ public class DynFilteredPointList : IPointList, IPointListEdit
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// Instance of a List of x values
+ /// </summary>
+ private List<double> _x;
+ /// <summary>
+ /// Instance of a List of y values
+ /// </summary>
+ private List<double> _y;
+
+ /// <summary>
+ /// Instance of an array of filtered x value indices
+ /// </summary>
+ private List<int> _filtdInds;
+
+ /// <summary>
+ /// This is the maximum number of points that you want to see in the filtered dataset
+ /// </summary>
+ private int _maxPts = -1;
+
+ /// <summary>
+ /// The min index of the filtered data bounds
+ /// </summary>
+ private int _minBoundIndex = -1;
+ /// <summary>
+ /// The max index of the filtered data bounds
+ /// </summary>
+ private int _maxBoundIndex = -1;
+
+ /// <summary>
+ /// Determines if the high/low logic will be used.
+ /// </summary>
+ private bool _isApplyHighLowLogic = true;
+
+ /// <summary>
+ /// Lock to prevent filtered data from being read while it is being generated by FilterData().
+ /// </summary>
+ private object _filtLockObject = new object();
+
+ /// <summary>
+ /// The number of points per segment to filter. In each segment
+ /// the first, {min then max or max then min}, and last points are used.
+ /// This constant must not be changed without rewriting the
+ /// filtering algorithm (i.e. FilterData()).
+ /// </summary>
+ private const int POINTS_PER_SEGMENT = 4;
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="PointPair"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <remarks>
+ /// Returns <see cref="PointPairBase.Missing" /> for any value of <see paramref="index" />
+ /// that is outside of its corresponding array bounds.
+ /// </remarks>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="PointPair"/> object to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object reference.</value>
+ public PointPair this[int index]
+ {
+ get
+ {
+ lock (_filtLockObject)
+ {
+ double xVal = PointPair.Missing;
+ double yVal = PointPair.Missing;
+ if (index >= 0 && index < this.Count)
+ {
+ int fIndex = _filtdInds[index];
+ if (fIndex < _x.Count)
+ {
+ xVal = _x[fIndex];
+ yVal = _y[fIndex];
+ }
+ xVal = _x[_filtdInds[index]];
+ yVal = _y[_filtdInds[index]];
+ }
+
+ return new PointPair(xVal, yVal, PointPair.Missing, null);
+ }
+ }
+ set
+ {
+ lock (_filtLockObject)
+ {
+ int ind = _x.BinarySearch(value.X);
+
+ if (ind < 0)
+ ind = ~ind;
+
+ if (ind <= _x.Count)
+ {
+ _x.Insert(ind, value.X);
+ _y.Insert(ind, value.Y);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the number of points according to the current state of the filter.
+ /// </summary>
+ public int Count
+ {
+ get { return _filtdInds.Count; }
+ }
+
+ /// <summary>
+ /// Returns the number of points in the underlying data set.
+ /// </summary>
+ public int UnFilteredCount
+ {
+ get { return _x.Count; }
+ }
+
+ /// <summary>
+ /// Gets the desired number of filtered points to output. You can set this value by
+ /// calling <see cref="FilterData" />.
+ /// </summary>
+ public int MaxPts
+ {
+ get { return _maxPts; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the High-Low filtering logic
+ /// will be applied.
+ /// </summary>
+ /// <remarks>
+ /// The high-low filtering logic takes 4 points of each segment.
+ /// The first point, the highest then lowest Y value or vice versa
+ /// (depending which came first) and then last value of this segment.
+ /// Set this value to true to apply this logic, or false to just use whatever
+ /// value lies at the start of each quarter of each segment.
+ /// </remarks>
+ public bool IsApplyHighLowLogic
+ {
+ get { return _isApplyHighLowLogic; }
+ set { _isApplyHighLowLogic = value; }
+ }
+
+ /// <summary>
+ /// Gets the index of minimum value for the range of X data that are included in the filtered result.
+ /// </summary>
+ public int MinBoundIndex
+ {
+ get { return _minBoundIndex; }
+ }
+
+ /// <summary>
+ /// Gets the index of maximum value for the range of X data that are included in the filtered result.
+ /// </summary>
+ public int MaxBoundIndex
+ {
+ get { return _maxBoundIndex; }
+ }
+
+ /// <summary>
+ /// Gets the x values in the underlying data set.
+ /// </summary>
+ public List<double> UnFilteredX
+ {
+ get { return _x; }
+ }
+
+ /// <summary>
+ /// Gets the y values in the underlying data set.
+ /// </summary>
+ public List<double> UnFilteredY
+ {
+ get { return _y; }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Constructor to initialize the PointPairList with no PointPairs.
+ /// </summary>
+ public DynFilteredPointList()
+ {
+ _x = new List<double>();
+ _y = new List<double>();
+
+ _filtdInds = new List<int>();
+ }
+
+ /// <summary>
+ /// Constructor to initialize the PointPairList from two arrays of
+ /// type double.
+ /// <remarks>Assumes the _x and _y arrays are monotonically increasing</remarks>
+ /// </summary>
+ public DynFilteredPointList(List<double> x, List<double> y)
+ {
+ _x = x;
+ _y = y;
+
+ _filtdInds = new List<int>();
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <remarks>Assumes the _x and _y arrays are monotonically increasing</remarks>
+ /// <param name="rhs">The FilteredPointList from which to copy</param>
+ public DynFilteredPointList(DynFilteredPointList rhs)
+ {
+ // the only way we can deep Clone a list is to use GetRange
+ _x = new List<double>(rhs._x.GetRange(0, rhs._x.Count).ToArray()); // Clone rhs._x
+ _y = new List<double>(rhs._y.GetRange(0, rhs._y.Count).ToArray()); // Clone rhs._y
+
+ _filtdInds = new List<int>(rhs._filtdInds.GetRange(0, rhs._filtdInds.Count)); // Clone rhs._filtdPts
+
+ _minBoundIndex = rhs._minBoundIndex;
+ _maxBoundIndex = rhs._maxBoundIndex;
+ _maxPts = rhs._maxPts;
+
+ _isApplyHighLowLogic = rhs._isApplyHighLowLogic;
+ }
+
+ /// <summary>
+ /// Deep-copy clone routine
+ /// </summary>
+ /// <returns>A new, independent copy of the FilteredPointList</returns>
+ virtual public object Clone()
+ {
+ return new DynFilteredPointList(this);
+ }
+
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Set the data bounds to the specified minimum, maximum, and point count.
+ /// Use values of min=double.MinValue and max=double.MaxValue to get the full range of data.
+ /// Use maxPts=-1 to not limit the number of points. Call this method anytime the zoom
+ /// range is changed or data is added to the list.
+ /// </summary>
+ /// <remarks>
+ /// This function works correctly with non-equally spaced data.
+ /// The filtering algorithm divides the whole range into segments containing
+ /// 4 points each. These 4 points are the first point in the segment, the min
+ /// then max or max then min (depending which appears first in the underlying dataset),
+ /// and the last point.
+ /// Hence, in the filtered dataset, the number of points is always a multiple of 4.
+ /// </remarks>
+ /// <param name="min">The lower bound for the X data of interest</param>
+ /// <param name="max">The upper bound for the X data of interest</param>
+ /// <param name="maxPts">The maximum number of points allowed to be output by the filter.
+ /// Setting this to 4 times the number of pixels on the X axis produces the
+ /// best results.</param>
+ /// <param name="filterOnlyNewData">True to filter only new data since the
+ /// last time FilterData was called, plus last filter subrange.</param>
+ public void FilterData(double min, double max, int maxPts, bool filterOnlyNewData)
+ {
+ lock (_filtLockObject)
+ {
+ _maxPts = maxPts;
+
+ setMinMaxBoundIndex(min, max);
+
+ if (_maxBoundIndex <= _minBoundIndex)
+ return;
+
+ if (!filterOnlyNewData)
+ _filtdInds.Clear();
+
+ int elemsToFilter = (_maxBoundIndex - _minBoundIndex) + 1; // +1 for last pt to touch Y2Axis
+
+ // if too few points (or we've been asked not to filter), don't filter
+ if (_x.Count > 0 && (elemsToFilter < maxPts || maxPts == -1))
+ {
+ _filtdInds.Clear();
+ for (int i = _minBoundIndex; i < (_minBoundIndex + elemsToFilter); i++)
+ _filtdInds.Add(i);
+
+ return;
+ }
+
+ // each segment will contain 4 points,
+ // the first, {min then max or max then min}, and last.
+ double segmentWidth = ((max - min) * POINTS_PER_SEGMENT) / maxPts;
+
+ int ind = _minBoundIndex;
+
+ // if filterOnlyNewData, delete the last segment and
+ // move ind to the start of the (empty) last segment
+ if (filterOnlyNewData && _filtdInds.Count >= POINTS_PER_SEGMENT)
+ {
+ // remove last segment (i.e. 4 points)
+ for (int i = 0; i < POINTS_PER_SEGMENT; i++)
+ _filtdInds.RemoveAt(_filtdInds.Count - 1);
+
+ ind = _filtdInds[_filtdInds.Count - 1] + 1;
+ }
+
+ while (ind <= _maxBoundIndex)
+ {
+ double nextSegmentStart = _x[ind] + segmentWidth;
+
+ if (_isApplyHighLowLogic)
+ {
+ _filtdInds.Add(ind); // add the first element of the segment
+
+ int minInd, maxInd;
+
+ // we will check the value of every element of this segment
+ // and then pick the min and max and add them to _xFiltd and _yFiltd
+ // in the order that they appeared in the segment.
+ // NB: the index (ind) is moved to the start of the next segment
+ getMinMaxIndices(ref ind, nextSegmentStart, out minInd, out maxInd);
+
+ // add the min and max of this segment in the order they appeared
+ addMinMaxIndices(minInd, maxInd);
+
+ // add last element of this segment (not the start of the next)
+ _filtdInds.Add(ind - 1);
+ }
+ else
+ {
+ // we need to add 4 elements in this segment and we are not applying
+ // highLowLogic so we add the first, the 1/4th, the middle and 3/4th
+ for (int i = 1; i <= POINTS_PER_SEGMENT; i++)
+ {
+ // add the next point of this segment
+ _filtdInds.Add(ind);
+
+ if (ind >= _maxBoundIndex)
+ {
+ ind++;
+ break;
+ }
+
+ // move to the next quarter of this segment
+ moveIndexToXVal(ref ind, nextSegmentStart + ((segmentWidth * i) / POINTS_PER_SEGMENT));
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Appends a point to the end of the list. The data are passed in as a <see cref="PointPair" />
+ /// object.
+ /// </summary>
+ /// <remarks>A data point that is not monotonically increasing will not be added.</remarks>
+ /// <param name="point">The <see cref="PointPair" /> object containing the data to be added.</param>
+ public void Add(PointPair point)
+ {
+ this.Add(point.X, point.Y);
+ }
+
+ /// <summary>
+ /// Appends a point to the end of the list. The data are passed in as two <see cref="Double" />
+ /// types.
+ /// </summary>
+ /// <remarks>A data point that is not monotonically increasing will not be added.</remarks>
+ /// <param name="x">The <see cref="Double" /> value containing the X data to be added.</param>
+ /// <param name="y">The <see cref="Double" /> value containing the Y data to be added.</param>
+ public void Add(double x, double y)
+ {
+ if (_x.Count > 0 && x < _x[_x.Count - 1])
+ return;
+
+ _x.Add(x);
+ try
+ {
+ _y.Add(y);
+ }
+ catch (Exception)
+ {
+ _x.RemoveAt(_x.Count - 1); // Remove last x since adding corresponding y failed
+ throw;
+ }
+
+ _maxPts++;
+ }
+
+ /// <summary>
+ /// Remove an old item from the list containing the whole underlying data.
+ /// </summary>
+ /// <remarks><see cref="FilterData"/> should be called after removing a point
+ /// to ensure the filtered subset contains valid indices into the underlying list.
+ /// </remarks>
+ /// <returns>The removed item or if the list was empty, null.</returns>
+ public PointPair Remove()
+ {
+ if (_x.Count == 0)
+ return null;
+
+ int prevLastIndex = _x.Count - 1;
+
+ PointPair pp = new PointPair(_x[prevLastIndex], _y[prevLastIndex]);
+
+ _x.RemoveAt(prevLastIndex);
+ _y.RemoveAt(prevLastIndex);
+
+ return pp;
+ }
+
+ /// <summary>
+ /// Remove the <see cref="PointPair" /> at the specified index in the list
+ /// containing the whole underlying data.
+ /// <remarks><see cref="FilterData"/> should be called after removing a point
+ /// to ensure the filtered subset contains valid indices into the underlying list.
+ /// </remarks>
+ /// </summary>
+ /// <param name="index">The ordinal position of the item to be removed.
+ /// Throws an <see cref="ArgumentOutOfRangeException" /> if index is less than
+ /// zero or greater than or equal to <see cref="Count" />
+ /// </param>
+ public void RemoveAt(int index)
+ {
+ if (index >= _x.Count || index >= _x.Count || index < 0)
+ throw new ArgumentOutOfRangeException();
+
+ _x.RemoveAt(index);
+ _y.RemoveAt(index);
+ }
+
+ /// <summary>
+ /// Clears all data points from the list. After calling this method,
+ /// <see cref="IPointList.Count" /> will be zero.
+ /// </summary>
+ public void Clear()
+ {
+ _x.Clear();
+ _y.Clear();
+
+ _filtdInds.Clear();
+
+ _maxPts = -1;
+ _minBoundIndex = -1;
+ _maxBoundIndex = -1;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Display the number of points in this list.
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return this.Count + " of " + _x.Count + " points";
+ }
+ #region Private Methods
+ /// <summary>
+ /// Set <see cref="_minBoundIndex"/> and <see cref="_maxBoundIndex"/>
+ /// based on the X values passed by the user.
+ /// </summary>
+ private void setMinMaxBoundIndex(double min, double max)
+ {
+ // find the index of the start and end of the bounded range
+ int first = _x.BinarySearch(min);
+ int last = _x.BinarySearch(max);
+
+ // Make sure the bounded indices are legitimate
+ // if BinarySearch() doesn't find the value, it returns the bitwise
+ // complement of the index of the 1st element larger than the sought value
+
+ if (first < 0)
+ {
+ if (first == -1)
+ first = 0;
+ else
+ first = ~(first + 1);
+ }
+
+ if (last < 0)
+ last = ~last;
+
+ if (last >= _x.Count && _x.Count > 0)
+ last = _x.Count - 1;
+
+ _minBoundIndex = first;
+ _maxBoundIndex = last;
+ }
+
+ /// <summary>
+ /// Gets the indices of the minimum and maximum within the subrange
+ /// between index and nextSegment which is the value of X. Index is
+ /// updated to the index of nextSegment.
+ /// </summary>
+ private void getMinMaxIndices(ref int index, double nextSegmentStart,
+ out int minIndex, out int maxIndex)
+ {
+ double y;
+ double miny = Double.MaxValue, maxy = Double.MinValue;
+
+ minIndex = maxIndex = index;
+
+ while (_x[index] < nextSegmentStart)
+ {
+ y = _y[index];
+
+ if (y > maxy)
+ {
+ maxy = y;
+ maxIndex = index;
+ }
+
+ if (y < miny)
+ {
+ miny = y;
+ minIndex = index;
+ }
+
+ index++;
+ if (index >= _x.Count || index >= _y.Count)
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Add min and max indices to the end of <see cref="_filtdInds"/>
+ /// </summary>
+ private void addMinMaxIndices(int minIndex, int maxIndex)
+ {
+ if (minIndex < maxIndex)
+ {
+ _filtdInds.Add(minIndex);
+ _filtdInds.Add(maxIndex);
+ }
+ else
+ {
+ _filtdInds.Add(maxIndex);
+ _filtdInds.Add(minIndex);
+ }
+ }
+
+ /// <summary>
+ /// Search <see cref="_x"/> for xVal and set the index to it.
+ /// </summary>
+ private void moveIndexToXVal(ref int index, double xVal)
+ {
+ int ind = _x.BinarySearch(xVal);
+
+ if (ind < 0)
+ ind = ~ind;
+
+ if (ind >= _x.Count && _x.Count > 0)
+ ind = _x.Count - 1;
+
+ index = ind;
+ }
+ #endregion
+ }
+}
diff --git a/ZedGraph/EllipseObj.cs b/ZedGraph/EllipseObj.cs
new file mode 100644
index 0000000..a01aa5c
--- /dev/null
+++ b/ZedGraph/EllipseObj.cs
@@ -0,0 +1,258 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents a bordered and/or filled ellipse object on
+ /// the graph. A list of EllipseObj objects is maintained by the
+ /// <see cref="GraphObjList"/> collection class. The ellipse is defined
+ /// as the ellipse that would be contained by the rectangular box as
+ /// defined by the <see cref="Location"/> property.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.3 $ $Date: 2007-01-25 07:56:08 $ </version>
+ [Serializable]
+ public class EllipseObj : BoxObj, ICloneable, ISerializable
+ {
+ #region Constructors
+ /// <overloads>Constructors for the <see cref="EllipseObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the position and size
+ /// of the <see cref="EllipseObj"/> to be pre-specified. Other properties are defaulted.
+ /// </summary>
+ /// <param name="x">The x location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="y">The y location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="width">The width of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="height">The height of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ public EllipseObj( double x, double y, double width, double height )
+ : base( x, y, width, height )
+ {
+ }
+
+ /// <summary>
+ /// A default constructor that places the <see cref="EllipseObj"/> at location (0,0),
+ /// with width/height of (1,1). Other properties are defaulted.
+ /// </summary>
+ public EllipseObj() : base()
+ {
+ }
+
+ /// <summary>
+ /// A constructor that allows the position, border color, and solid fill color
+ /// of the <see cref="EllipseObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="borderColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the ellipse border</param>
+ /// <param name="fillColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the ellipse fill (will be a solid color fill)</param>
+ /// <param name="x">The x location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="y">The y location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="width">The width of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="height">The height of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ public EllipseObj( double x, double y, double width, double height, Color borderColor, Color fillColor )
+ : base( x, y, width, height, borderColor, fillColor )
+ {
+ }
+
+ /// <summary>
+ /// A constructor that allows the position, border color, and two-color
+ /// gradient fill colors
+ /// of the <see cref="EllipseObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="borderColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the ellipse border</param>
+ /// <param name="fillColor1">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the start of the ellipse gradient fill</param>
+ /// <param name="fillColor2">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the end of the ellipse gradient fill</param>
+ /// <param name="x">The x location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="y">The y location for this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="width">The width of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ /// <param name="height">The height of this <see cref="BoxObj" />. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame" />.</param>
+ public EllipseObj( double x, double y, double width, double height, Color borderColor,
+ Color fillColor1, Color fillColor2 ) :
+ base( x, y, width, height, borderColor, fillColor1, fillColor2 )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="EllipseObj"/> object from
+ /// which to copy</param>
+ public EllipseObj( BoxObj rhs ) : base( rhs )
+ {
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new EllipseObj Clone()
+ {
+ return new EllipseObj( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected EllipseObj( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema3", schema3 );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this object to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ // Convert the arrow coordinates from the user coordinate system
+ // to the screen coordinate system
+ RectangleF pixRect = this.Location.TransformRect( pane );
+
+ if ( Math.Abs( pixRect.Left ) < 100000 &&
+ Math.Abs( pixRect.Top ) < 100000 &&
+ Math.Abs( pixRect.Right ) < 100000 &&
+ Math.Abs( pixRect.Bottom ) < 100000 )
+ {
+ if ( _fill.IsVisible )
+ using ( Brush brush = _fill.MakeBrush( pixRect ) )
+ g.FillEllipse( brush, pixRect );
+
+ if ( _border.IsVisible )
+ using ( Pen pen = _border.GetPen( pane, scaleFactor ) )
+ g.DrawEllipse( pen, pixRect );
+ }
+ }
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="BoxObj"/>.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ if ( ! base.PointInBox(pt, pane, g, scaleFactor ) )
+ return false;
+
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ RectangleF pixRect = _location.TransformRect( pane );
+
+ using ( GraphicsPath path = new GraphicsPath() )
+ {
+ path.AddEllipse( pixRect );
+ return path.IsVisible( pt );
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ErrorBar.cs b/ZedGraph/ErrorBar.cs
new file mode 100644
index 0000000..f2f671f
--- /dev/null
+++ b/ZedGraph/ErrorBar.cs
@@ -0,0 +1,387 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This class handles the drawing of the curve <see cref="ErrorBar"/> objects.
+ /// The Error Bars are the vertical lines with a symbol at each end.
+ /// </summary>
+ /// <remarks>To draw "I-Beam" bars, the symbol type defaults to
+ /// <see cref="SymbolType.HDash"/>, which is just a horizontal line.
+ /// If <see cref="BarBase"/> is Y-oriented, then the symbol type should be
+ /// set to <see cref="SymbolType.VDash"/> to get the same effect.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.21 $ $Date: 2007-08-10 16:22:54 $ </version>
+ [Serializable]
+ public class ErrorBar : ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores the visibility of this
+ /// <see cref="ErrorBar"/>. Use the public
+ /// property <see cref="IsVisible"/> to access this value. If this value is
+ /// false, the symbols will not be shown.
+ /// </summary>
+ private bool _isVisible;
+ /// <summary>
+ /// Private field that stores the error bar color. Use the public
+ /// property <see cref="Color"/> to access this value.
+ /// </summary>
+ private Color _color;
+ /// <summary>
+ /// Private field that stores the pen width for this error bar. Use the public
+ /// property <see cref="PenWidth"/> to access this value.
+ /// </summary>
+ private float _penWidth;
+ /// <summary>
+ /// private field that contains the symbol element that will be drawn
+ /// at the top and bottom of the error bar. Use the public property
+ /// <see cref="Symbol"/> to access this value.
+ /// </summary>
+ private Symbol _symbol;
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ZedGraph.ErrorBar"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default Symbol properties
+ /// <summary>
+ /// The default size for curve symbols
+ /// (<see cref="ZedGraph.Symbol.Size"/> property),
+ /// in units of points.
+ /// </summary>
+ public static float Size = 7;
+ /// <summary>
+ /// The default pen width to be used for drawing error bars
+ /// (<see cref="ErrorBar.PenWidth"/> property). Units are points.
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The default display mode for symbols (<see cref="ErrorBar.IsVisible"/> property).
+ /// true to display symbols, false to hide them.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// The default color for drawing error bars (<see cref="ErrorBar.Color"/> property).
+ /// </summary>
+ public static Color Color = Color.Red;
+ /// <summary>
+ /// The default symbol for drawing at the top and bottom of the
+ /// error bar (see <see cref="ErrorBar.Symbol"/>).
+ /// </summary>
+ public static SymbolType Type = SymbolType.HDash;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets or sets a property that shows or hides the <see cref="ErrorBar"/>.
+ /// </summary>
+ /// <value>true to show the error bar, false to hide it</value>
+ /// <seealso cref="Default.IsVisible"/>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> data for this
+ /// <see cref="ErrorBar"/>.
+ /// </summary>
+ /// <remarks>This property only controls the color of
+ /// the vertical line. The symbol color is controlled separately in
+ /// the <see cref="Symbol"/> property.
+ /// </remarks>
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; }
+ }
+ /// <summary>
+ /// The pen width to be used for drawing error bars
+ /// Units are points.
+ /// </summary>
+ /// <remarks>This property only controls the pen width for the
+ /// vertical line. The pen width for the symbol outline is
+ /// controlled separately by the <see cref="Symbol"/> property.
+ /// </remarks>
+ public float PenWidth
+ {
+ get { return _penWidth; }
+ set { _penWidth = value; }
+ }
+ /// <summary>
+ /// Contains the symbol element that will be drawn
+ /// at the top and bottom of the error bar.
+ /// </summary>
+ public Symbol Symbol
+ {
+ get { return _symbol; }
+ set { _symbol = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default constructor that sets all <see cref="ErrorBar"/> properties to
+ /// default values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public ErrorBar() : this( Default.Color )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets the
+ /// <see cref="Color"/> as specified, and the remaining
+ /// <see cref="ErrorBar"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="color">A <see cref="Color"/> value indicating
+ /// the color of the symbol
+ /// </param>
+ public ErrorBar( Color color )
+ {
+ _symbol = new Symbol( Default.Type, color );
+ _symbol.Size = Default.Size;
+ _color = color;
+ _penWidth = Default.PenWidth;
+ _isVisible = Default.IsVisible;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ErrorBar"/> object from which to copy</param>
+ public ErrorBar( ErrorBar rhs )
+ {
+ _color = rhs.Color;
+ _isVisible = rhs.IsVisible;
+ _penWidth = rhs.PenWidth;
+ _symbol = rhs.Symbol.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ErrorBar Clone()
+ {
+ return new ErrorBar( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected ErrorBar( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _isVisible = info.GetBoolean( "isVisible" );
+ _color = (Color) info.GetValue( "color", typeof(Color) );
+ _penWidth = info.GetSingle( "penWidth" );
+ _symbol = (Symbol) info.GetValue( "symbol", typeof(Symbol) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "color", _color );
+ info.AddValue( "penWidth", _penWidth );
+ info.AddValue( "symbol", _symbol );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Draw the <see cref="ErrorBar"/> to the specified <see cref="Graphics"/>
+ /// device at the specified location.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="isXBase">boolean value that indicates if the "base" axis for this
+ /// <see cref="ErrorBar"/> is the X axis. True for an <see cref="XAxis"/> base,
+ /// false for a <see cref="YAxis"/> or <see cref="Y2Axis"/> base.</param>
+ /// <param name="pixBase">The independent axis position of the center of the error bar in
+ /// pixel units</param>
+ /// <param name="pixValue">The dependent axis position of the top of the error bar in
+ /// pixel units</param>
+ /// <param name="pixLowValue">The dependent axis position of the bottom of the error bar in
+ /// pixel units</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.</param>
+ /// <param name="pen">A pen with attributes of <see cref="Color"/> and
+ /// <see cref="PenWidth"/> for this <see cref="ErrorBar"/></param>
+ /// <param name="dataValue">The data value to be used for a value-based
+ /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>,
+ /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param>
+ /// <param name="isSelected">Indicates that the <see cref="ErrorBar" /> should be drawn
+ /// with attributes from the <see cref="Selection" /> class.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, bool isXBase,
+ float pixBase, float pixValue,
+ float pixLowValue, float scaleFactor, Pen pen, bool isSelected,
+ PointPair dataValue )
+ {
+ if ( isXBase )
+ {
+ g.DrawLine( pen, pixBase, pixValue, pixBase, pixLowValue );
+ _symbol.DrawSymbol( g, pane, (int)pixBase, (int)pixValue,
+ scaleFactor, isSelected, dataValue );
+ _symbol.DrawSymbol( g, pane, (int)pixBase, (int)pixLowValue,
+ scaleFactor, isSelected, dataValue );
+ }
+ else
+ {
+ g.DrawLine( pen, pixValue, pixBase, pixLowValue, pixBase );
+ _symbol.DrawSymbol( g, pane, (int)pixValue, (int)pixBase,
+ scaleFactor, isSelected, dataValue );
+ _symbol.DrawSymbol( g, pane, (int)pixLowValue, (int)pixBase,
+ scaleFactor, isSelected, dataValue );
+ }
+ }
+
+
+ /// <summary>
+ /// Draw all the <see cref="ErrorBar"/>'s to the specified <see cref="Graphics"/>
+ /// device as a an error bar at each defined point.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="CurveItem"/> object representing the
+ /// <see cref="Bar"/>'s to be drawn.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, ErrorBarItem curve,
+ Axis baseAxis, Axis valueAxis, float scaleFactor )
+ {
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+
+ float pixBase, pixValue, pixLowValue;
+ double scaleBase, scaleValue, scaleLowValue;
+
+ if ( curve.Points != null && this.IsVisible )
+ {
+ using ( Pen pen = !curve.IsSelected ? new Pen( _color, _penWidth ) :
+ new Pen( Selection.Border.Color, Selection.Border.Width ) )
+ {
+ // Loop over each defined point
+ for ( int i = 0; i < curve.Points.Count; i++ )
+ {
+ valueHandler.GetValues( curve, i, out scaleBase,
+ out scaleLowValue, out scaleValue );
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !curve.Points[i].IsInvalid3D &&
+ ( scaleBase > 0 || !baseAxis._scale.IsLog ) &&
+ ( ( scaleValue > 0 && scaleLowValue > 0 ) || !valueAxis._scale.IsLog ) )
+ {
+ pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, scaleBase );
+ pixValue = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, scaleValue );
+ pixLowValue = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, scaleLowValue );
+
+ //if ( this.fill.IsGradientValueType )
+ // brush = fill.MakeBrush( _rect, _points[i] );
+
+ this.Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis, pixBase, pixValue,
+ pixLowValue, scaleFactor, pen, curve.IsSelected,
+ curve.Points[i] );
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ErrorBarItem.cs b/ZedGraph/ErrorBarItem.cs
new file mode 100644
index 0000000..fba2df0
--- /dev/null
+++ b/ZedGraph/ErrorBarItem.cs
@@ -0,0 +1,363 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates an "Error Bar" curve type that displays a vertical or horizontal
+ /// line with a symbol at each end.
+ /// </summary>
+ /// <remarks>The <see cref="ErrorBarItem"/> type is intended for displaying
+ /// confidence intervals, candlesticks, stock High-Low charts, etc. It is
+ /// technically not a bar, since it is drawn as a vertical or horizontal line.
+ /// The default symbol at each end of the "bar" is <see cref="SymbolType.HDash"/>,
+ /// which creates an "I-Beam". For horizontal bars
+ /// (<see cref="ZedGraph.BarBase.Y"/> or
+ /// <see cref="ZedGraph.BarBase.Y2"/>), you will need to change the symbol to
+ /// <see cref="SymbolType.VDash"/> to get horizontal "I-Beams".
+ /// Since the horizontal segments are actually symbols, their widths are
+ /// controlled by the symbol size in <see cref="ZedGraph.ErrorBar.Symbol"/>,
+ /// specified in points (1/72nd inch). The position of each "I-Beam" is set
+ /// according to the <see cref="PointPair"/> values. The independent axis
+ /// is assigned with <see cref="BarSettings.Base"/>, and is a
+ /// <see cref="ZedGraph.BarBase"/> enum type.</remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.19 $ $Date: 2007-04-16 00:03:01 $ </version>
+ [Serializable]
+ public class ErrorBarItem : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="ZedGraph.ErrorBar"/>
+ /// class defined for this <see cref="ErrorBarItem"/>. Use the public
+ /// property <see cref="ErrorBar"/> to access this value.
+ /// </summary>
+ private ErrorBar _bar;
+
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets a reference to the <see cref="ZedGraph.ErrorBar"/> class defined
+ /// for this <see cref="ErrorBarItem"/>.
+ /// </summary>
+ public ErrorBar Bar
+ {
+ get { return _bar; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return pane._barSettings.Base == BarBase.X;
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="ErrorBarItem"/>, specifying only the legend label.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ public ErrorBarItem( string label ) : base( label )
+ {
+ _bar = new ErrorBar();
+ }
+
+ /// <summary>
+ /// Create a new <see cref="ErrorBarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the X axis values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the Y axis values for this curve</param>
+ /// <param name="lowValue">An array of double precision values that define
+ /// the lower dependent values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> properties.
+ /// </param>
+ public ErrorBarItem( string label, double[] x, double[] y, double[] lowValue,
+ System.Drawing.Color color )
+ : this( label, new PointPairList( x, y, lowValue ), color )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="ErrorBarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision values that define
+ /// the X, Y and lower dependent values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> properties.
+ /// </param>
+ public ErrorBarItem( string label, IPointList points, Color color )
+ : base( label, points )
+ {
+ _bar = new ErrorBar( color );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ErrorBarItem"/> object from which to copy</param>
+ public ErrorBarItem( ErrorBarItem rhs ) : base( rhs )
+ {
+ _bar = new ErrorBar( rhs.Bar );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ErrorBarItem Clone()
+ {
+ return new ErrorBarItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected ErrorBarItem( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _bar = (ErrorBar) info.GetValue( "bar", typeof(ErrorBar) );
+
+ // This is now just a dummy variable, since barBase was removed
+ BarBase barBase = (BarBase) info.GetValue( "barBase", typeof(BarBase) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "bar", _bar );
+
+ // BarBase is now just a dummy value, since the GraphPane.BarBase is used exclusively
+ info.AddValue( "barBase", BarBase.X );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Do all rendering associated with this <see cref="ErrorBarItem"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">The ordinal position of the current <see cref="ErrorBarItem"/>
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( _isVisible )
+ {
+ _bar.Draw( g, pane, this, this.BaseAxis( pane ),
+ this.ValueAxis( pane ), scaleFactor );
+ }
+ }
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="ErrorBarItem"/> at the specified location
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect,
+ float scaleFactor )
+ {
+ float pixBase, pixValue, pixLowValue;
+
+ if ( pane._barSettings.Base == BarBase.X )
+ {
+ pixBase = rect.Left + rect.Width / 2.0F;
+ pixValue = rect.Top;
+ pixLowValue = rect.Bottom;
+ }
+ else
+ {
+ pixBase = rect.Top + rect.Height / 2.0F;
+ pixValue = rect.Right;
+ pixLowValue = rect.Left;
+ }
+
+ using ( Pen pen = new Pen( _bar.Color, _bar.PenWidth ) )
+ {
+ this.Bar.Draw( g, pane, pane._barSettings.Base == BarBase.X, pixBase, pixValue,
+ pixLowValue, scaleFactor, pen, false, null );
+ }
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ override public bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = string.Empty;
+
+ if ( i < 0 || i >= _points.Count )
+ return false;
+
+ Axis valueAxis = ValueAxis( pane );
+ Axis baseAxis = BaseAxis( pane );
+
+ float scaledSize = _bar.Symbol.Size * pane.CalcScaleFactor();
+
+ // pixBase = pixel value for the bar center on the base axis
+ // pixHiVal = pixel value for the bar top on the value axis
+ // pixLowVal = pixel value for the bar bottom on the value axis
+ float pixBase, pixHiVal, pixLowVal;
+
+ float clusterWidth = pane.BarSettings.GetClusterWidth();
+ float barWidth = GetBarWidth( pane );
+ float clusterGap = pane._barSettings.MinClusterGap * barWidth;
+ float barGap = barWidth * pane._barSettings.MinBarGap;
+
+ // curBase = the scale value on the base axis of the current bar
+ // curHiVal = the scale value on the value axis of the current bar
+ // curLowVal = the scale value of the bottom of the bar
+ double curBase, curLowVal, curHiVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ valueHandler.GetValues( this, i, out curBase, out curLowVal, out curHiVal );
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !_points[i].IsInvalid3D )
+ {
+ // calculate a pixel value for the top of the bar on value axis
+ pixLowVal = valueAxis.Scale.Transform( _isOverrideOrdinal, i, curLowVal );
+ pixHiVal = valueAxis.Scale.Transform( _isOverrideOrdinal, i, curHiVal );
+ // calculate a pixel value for the center of the bar on the base axis
+ pixBase = baseAxis.Scale.Transform( _isOverrideOrdinal, i, curBase );
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - scaledSize / 2.0F;
+
+ // Draw the bar
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixSide, pixLowVal,
+ pixSide + scaledSize, pixHiVal );
+ else
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixLowVal, pixSide,
+ pixHiVal, pixSide + scaledSize );
+
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ExponentScale.cs b/ZedGraph/ExponentScale.cs
new file mode 100644
index 0000000..4529a35
--- /dev/null
+++ b/ZedGraph/ExponentScale.cs
@@ -0,0 +1,403 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The ExponentScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.Exponent" />.
+ /// </summary>
+ /// <remarks>
+ /// ExponentScale is a non-linear axis in which the values are scaled using an exponential function
+ /// with the <see cref="Scale.Exponent" /> property.
+ /// </remarks>
+ ///
+ /// <author> John Champion with contributions by jackply </author>
+ /// <version> $Revision: 1.8 $ $Date: 2007-04-16 00:03:01 $ </version>
+ [Serializable]
+ class ExponentScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public ExponentScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ExponentScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="ExponentScale" /></param>
+ public ExponentScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new ExponentScale( this, owner );
+ }
+
+ #endregion
+
+ #region properties
+
+ public override AxisType Type
+ {
+ get { return AxisType.Exponent; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Setup some temporary transform values in preparation for rendering the <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>
+ /// This method is typically called by the parent <see cref="GraphPane"/>
+ /// object as part of the <see cref="GraphPane.Draw"/> method. It is also
+ /// called by <see cref="GraphPane.GeneralTransform(double,double,CoordType)"/> and
+ /// <see cref="GraphPane.ReverseTransform( PointF, out double, out double )"/>
+ /// methods to setup for coordinate transformations.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="axis">
+ /// The parent <see cref="Axis" /> for this <see cref="Scale" />
+ /// </param>
+ override public void SetupScaleData( GraphPane pane, Axis axis )
+ {
+ base.SetupScaleData( pane, axis );
+
+ if ( _exponent > 0 )
+ {
+ _minLinTemp = Linearize( _min );
+ _maxLinTemp = Linearize( _max );
+ }
+ else if ( _exponent < 0 )
+ {
+ _minLinTemp = Linearize( _max );
+ _maxLinTemp = Linearize( _min );
+ }
+ }
+
+ /// <summary>
+ /// Convert a value to its linear equivalent for this type of scale.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to just return the value unchanged. However,
+ /// for <see cref="AxisType.Log" /> and <see cref="AxisType.Exponent" />,
+ /// it returns the log or power equivalent.
+ /// </remarks>
+ /// <param name="val">The value to be converted</param>
+ override public double Linearize( double val )
+ {
+ return SafeExp( val, _exponent );
+ }
+
+ /// <summary>
+ /// Convert a value from its linear equivalent to its actual scale value
+ /// for this type of scale.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to just return the value unchanged. However,
+ /// for <see cref="AxisType.Log" /> and <see cref="AxisType.Exponent" />,
+ /// it returns the anti-log or inverse-power equivalent.
+ /// </remarks>
+ /// <param name="val">The value to be converted</param>
+ override public double DeLinearize( double val )
+ {
+ return Math.Pow( val, 1 / _exponent );
+ }
+
+ /// <summary>
+ /// Determine the value for any major tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double)
+ /// </param>
+ /// <param name="tic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified major tic value (floating point double).
+ /// </returns>
+ override internal double CalcMajorTicValue( double baseVal, double tic )
+ {
+ if ( _exponent > 0.0 )
+ {
+ //return baseVal + Math.Pow ( (double) this.majorStep * tic, exp );
+ //baseVal is got from CalBase..., and it is exp..
+ return Math.Pow( Math.Pow( baseVal, 1 / _exponent ) + _majorStep * tic, _exponent );
+ }
+ else if ( _exponent < 0.0 )
+ {
+ //baseVal is got from CalBase..., and it is exp..
+ return Math.Pow( Math.Pow( baseVal, 1 / _exponent ) + _majorStep * tic, _exponent );
+ }
+
+ return 1.0;
+ }
+
+ /// <summary>
+ /// Determine the value for any minor tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double). This tic value is the base
+ /// reference for all tics (including minor ones).
+ /// </param>
+ /// <param name="iTic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified minor tic value (floating point double).
+ /// </returns>
+ override internal double CalcMinorTicValue( double baseVal, int iTic )
+ {
+ return baseVal + Math.Pow( (double) _majorStep * (double) iTic, _exponent );
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first minor tic mark
+ /// </summary>
+ /// <param name="baseVal">
+ /// The value of the first major tic for the axis.
+ /// </param>
+ /// <returns>
+ /// The ordinal position of the first minor tic, relative to the first major tic.
+ /// This value can be negative (e.g., -3 means the first minor tic is 3 minor step
+ /// increments before the first major tic.
+ /// </returns>
+ override internal int CalcMinorStart( double baseVal )
+ {
+ return (int) ( ( Math.Pow( _min, _exponent ) - baseVal ) / Math.Pow( _minorStep, _exponent ) );
+ }
+
+ /// <summary>
+ /// Select a reasonable exponential axis scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.Exponent"/> type axes, and it
+ /// is called by the general <see cref="Scale.PickScale"/> method. The exponential scale
+ /// relies on the <see cref="Scale.Exponent" /> property to set the scaling exponent. This
+ /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/> autorange settings.
+ /// In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/>
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values. For log axes, the MinorStep
+ /// value is not used.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <seealso cref="Scale.PickScale"/>
+ /// <seealso cref="AxisType.Exponent"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ // Test for trivial condition of range = 0 and pick a suitable default
+ if ( _max - _min < 1.0e-20 )
+ {
+ if ( _maxAuto )
+ _max = _max + 0.2 * ( _max == 0 ? 1.0 : Math.Abs( _max ) );
+ if ( _minAuto )
+ _min = _min - 0.2 * ( _min == 0 ? 1.0 : Math.Abs( _min ) );
+ }
+
+ // This is the zero-lever test. If minVal is within the zero lever fraction
+ // of the data range, then use zero.
+
+ if ( _minAuto && _min > 0 &&
+ _min / ( _max - _min ) < Default.ZeroLever )
+ _min = 0;
+
+ // Repeat the zero-lever test for cases where the maxVal is less than zero
+ if ( _maxAuto && _max < 0 &&
+ Math.Abs( _max / ( _max - _min ) ) <
+ Default.ZeroLever )
+ _max = 0;
+
+ // Calculate the new step size
+ if ( _majorStepAuto )
+ {
+ double targetSteps = ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ?
+ Default.TargetXSteps : Default.TargetYSteps;
+
+ // Calculate the step size based on target steps
+ _majorStep = CalcStepSize( _max - _min, targetSteps );
+
+ if ( _isPreventLabelOverlap )
+ {
+ // Calculate the maximum number of labels
+ double maxLabels = (double) this.CalcMaxLabels( g, pane, scaleFactor );
+
+ if ( maxLabels < ( _max - _min ) / _majorStep )
+ _majorStep = CalcBoundedStepSize( _max - _min, maxLabels );
+ }
+ }
+
+ // Calculate the new step size
+ if ( _minorStepAuto )
+ _minorStep = CalcStepSize( _majorStep,
+ ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ?
+ Default.TargetMinorXSteps : Default.TargetMinorYSteps );
+
+ // Calculate the scale minimum
+ if ( _minAuto )
+ _min = _min - MyMod( _min, _majorStep );
+
+ // Calculate the scale maximum
+ if ( _maxAuto )
+ _max = MyMod( _max, _majorStep ) == 0.0 ? _max :
+ _max + _majorStep - MyMod( _max, _majorStep );
+
+ // set the scale magnitude if required
+ if ( _magAuto )
+ {
+ // Find the optimal scale display multiple
+ double mag = 0;
+ double mag2 = 0;
+
+ if ( Math.Abs( _min ) > 1.0e-10 )
+ mag = Math.Floor( Math.Log10( Math.Abs( _min ) ) );
+ if ( Math.Abs( _max ) > 1.0e-10 )
+ mag2 = Math.Floor( Math.Log10( Math.Abs( _max ) ) );
+ if ( Math.Abs( mag2 ) > Math.Abs( mag ) )
+ mag = mag2;
+
+ // Do not use scale multiples for magnitudes below 4
+ if ( Math.Abs( mag ) <= 3 )
+ mag = 0;
+
+ // Use a power of 10 that is a multiple of 3 (engineering scale)
+ _mag = (int) ( Math.Floor( mag / 3.0 ) * 3.0 );
+ }
+
+ // Calculate the appropriate number of dec places to display if required
+ if ( _formatAuto )
+ {
+ int numDec = 0 - (int) ( Math.Floor( Math.Log10( _majorStep ) ) - _mag );
+ if ( numDec < 0 )
+ numDec = 0;
+ _format = "f" + numDec.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Make a value label for an <see cref="AxisType.Exponent" /> <see cref="Axis" />.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="Scale.IsLog"/>)
+ /// and text (<see cref="Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ override internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ double scaleMult = Math.Pow( (double) 10.0, _mag );
+ double val = Math.Pow( dVal, 1 / _exponent ) / scaleMult;
+ return val.ToString( _format );
+ }
+
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected ExponentScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Fill.cs b/ZedGraph/Fill.cs
new file mode 100644
index 0000000..5600bdd
--- /dev/null
+++ b/ZedGraph/Fill.cs
@@ -0,0 +1,1144 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that encapsulates color-fill properties for an object. The <see cref="Fill"/> class
+ /// is used in <see cref="PaneBase.Rect"/>, <see cref="Chart.Rect"/>, <see cref="Legend"/>,
+ /// <see cref="Bar"/>, and <see cref="Line"/> objects.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.22 $ $Date: 2007-01-26 09:01:49 $ </version>
+ [Serializable]
+ public class Fill : ISerializable, ICloneable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores the fill color. Use the public
+ /// property <see cref="Color"/> to access this value. This property is
+ /// only applicable if the <see cref="Type"/> is not <see cref="ZedGraph.FillType.None"/>.
+ /// </summary>
+ private Color _color;
+ /// <summary>
+ /// Private field that stores the secondary color for gradientByValue fills. Use the public
+ /// property <see cref="SecondaryValueGradientColor"/> to access this value. This property is
+ /// only applicable if the <see cref="Type"/> is <see cref="ZedGraph.FillType.GradientByX"/>,
+ /// <see cref="ZedGraph.FillType.GradientByY"/>, or <see cref="ZedGraph.FillType.GradientByZ"/>.
+ /// </summary>
+ private Color _secondaryValueGradientColor;
+ /// <summary>
+ /// Private field that stores the custom fill brush. Use the public
+ /// property <see cref="Brush"/> to access this value. This property is
+ /// only applicable if the
+ /// <see cref="Type"/> property is set to <see cref="ZedGraph.FillType.Brush"/>.
+ /// </summary>
+ protected Brush _brush;
+ /// <summary>
+ /// Private field that determines the type of color fill. Use the public
+ /// property <see cref="Type"/> to access this value. The fill color
+ /// is determined by the property <see cref="Color"/> or
+ /// <see cref="Brush"/>.
+ /// </summary>
+ private FillType _type;
+ /// <summary>
+ /// Private field that determines if the brush will be scaled to the bounding box
+ /// of the filled object. If this value is false, then the brush will only be aligned
+ /// with the filled object based on the <see cref="AlignH"/> and <see cref="AlignV"/>
+ /// properties.
+ /// </summary>
+ private bool _isScaled;
+ /// <summary>
+ /// Private field that determines how the brush will be aligned with the filled object
+ /// in the horizontal direction. This value is a <see cref="ZedGraph.AlignH"/> enumeration.
+ /// This field only applies if <see cref="IsScaled"/> is false.
+ /// properties.
+ /// </summary>
+ /// <seealso cref="AlignH"/>
+ /// <seealso cref="AlignV"/>
+ private AlignH _alignH;
+ /// <summary>
+ /// Private field that determines how the brush will be aligned with the filled object
+ /// in the vertical direction. This value is a <see cref="ZedGraph.AlignV"/> enumeration.
+ /// This field only applies if <see cref="IsScaled"/> is false.
+ /// properties.
+ /// </summary>
+ /// <seealso cref="AlignH"/>
+ /// <seealso cref="AlignV"/>
+ private AlignV _alignV;
+
+ private double _rangeMin;
+ private double _rangeMax;
+ private double _rangeDefault;
+ private Bitmap _gradientBM;
+
+ /// <summary>
+ /// Private field that saves the image passed to the constructor.
+ /// This is used strictly for serialization.
+ /// </summary>
+ private Image _image;
+ /// <summary>
+ /// Private field that saves the image wrapmode passed to the constructor.
+ /// This is used strictly for serialization.
+ /// </summary>
+ private WrapMode _wrapMode;
+ /// <summary>
+ /// Private field that saves the list of colors used to create the
+ /// <see cref="LinearGradientBrush"/> in the constructor. This is used strictly
+ /// for serialization.
+ /// </summary>
+ private Color[] _colorList;
+ /// <summary>
+ /// Private field that saves the list of positions used to create the
+ /// <see cref="LinearGradientBrush"/> in the constructor. This is used strictly
+ /// for serialization.
+ /// </summary>
+ private float[] _positionList;
+ /// <summary>
+ /// Private field the saves the angle of the fill. This is used strictly for serialization.
+ /// </summary>
+ private float _angle;
+
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Fill"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default Fill properties
+ /// <summary>
+ /// The default scaling mode for <see cref="Brush"/> fills.
+ /// This is the default value for the <see cref="Fill.IsScaled"/> property.
+ /// </summary>
+ public static bool IsScaled = true;
+ /// <summary>
+ /// The default horizontal alignment for <see cref="Brush"/> fills.
+ /// This is the default value for the <see cref="Fill.AlignH"/> property.
+ /// </summary>
+ public static AlignH AlignH = AlignH.Center;
+ /// <summary>
+ /// The default vertical alignment for <see cref="Brush"/> fills.
+ /// This is the default value for the <see cref="Fill.AlignV"/> property.
+ /// </summary>
+ public static AlignV AlignV = AlignV.Center;
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Generic initializer to default values
+ /// </summary>
+ private void Init()
+ {
+ _color = Color.White;
+ _secondaryValueGradientColor = Color.White;
+ _brush = null;
+ _type = FillType.None;
+ _isScaled = Default.IsScaled;
+ _alignH = Default.AlignH;
+ _alignV = Default.AlignV;
+ _rangeMin = 0.0;
+ _rangeMax = 1.0;
+ _rangeDefault = double.MaxValue;
+ _gradientBM = null;
+
+ _colorList = null;
+ _positionList = null;
+ _angle = 0;
+ _image = null;
+ _wrapMode = WrapMode.Tile;
+
+ }
+
+ /// <summary>
+ /// The default constructor. Initialized to no fill.
+ /// </summary>
+ public Fill()
+ {
+ Init();
+ }
+
+ /// <summary>
+ /// Constructor that specifies the color, brush, and type for this fill.
+ /// </summary>
+ /// <param name="color">The color of the fill for solid fills</param>
+ /// <param name="brush">A custom brush for fills. Can be a <see cref="SolidBrush"/>,
+ /// <see cref="LinearGradientBrush"/>, or <see cref="TextureBrush"/>.</param>
+ /// <param name="type">The <see cref="FillType"/> for this fill.</param>
+ public Fill( Color color, Brush brush, FillType type )
+ {
+ Init();
+ _color = color;
+ _brush = brush;
+ _type = type;
+ }
+
+ /// <summary>
+ /// Constructor that creates a solid color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Solid"/>, and setting <see cref="Color"/> to the
+ /// specified color value.
+ /// </summary>
+ /// <param name="color">The color of the solid fill</param>
+ public Fill( Color color )
+ {
+ Init();
+ _color = color;
+ if ( color != Color.Empty )
+ _type = FillType.Solid;
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors and angle.
+ /// </summary>
+ /// <param name="color1">The first color for the gradient fill</param>
+ /// <param name="color2">The second color for the gradient fill</param>
+ /// <param name="angle">The angle (degrees) of the gradient fill</param>
+ public Fill( Color color1, Color color2, float angle )
+ {
+ Init();
+ _color = color2;
+
+ ColorBlend blend = new ColorBlend( 2 );
+ blend.Colors[0] = color1;
+ blend.Colors[1] = color2;
+ blend.Positions[0] = 0.0f;
+ blend.Positions[1] = 1.0f;
+ _type = FillType.Brush;
+
+ this.CreateBrushFromBlend( blend, angle );
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors.
+ /// </summary>
+ /// <param name="color1">The first color for the gradient fill</param>
+ /// <param name="color2">The second color for the gradient fill</param>
+ public Fill( Color color1, Color color2 ) : this( color1, color2, 0.0F )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of three colors.
+ /// </summary>
+ /// <param name="color1">The first color for the gradient fill</param>
+ /// <param name="color2">The second color for the gradient fill</param>
+ /// <param name="color3">The third color for the gradient fill</param>
+ public Fill( Color color1, Color color2, Color color3 ) :
+ this( color1, color2, color3, 0.0f )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of three colors
+ /// </summary>
+ /// <param name="color1">The first color for the gradient fill</param>
+ /// <param name="color2">The second color for the gradient fill</param>
+ /// <param name="color3">The third color for the gradient fill</param>
+ /// <param name="angle">The angle (degrees) of the gradient fill</param>
+ public Fill( Color color1, Color color2, Color color3, float angle )
+ {
+ Init();
+ _color = color3;
+
+ ColorBlend blend = new ColorBlend( 3 );
+ blend.Colors[0] = color1;
+ blend.Colors[1] = color2;
+ blend.Colors[2] = color3;
+ blend.Positions[0] = 0.0f;
+ blend.Positions[1] = 0.5f;
+ blend.Positions[2] = 1.0f;
+ _type = FillType.Brush;
+
+ this.CreateBrushFromBlend( blend, angle );
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient multi-color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of many colors based on a <see cref="ColorBlend"/> object. The gradient
+ /// angle is defaulted to zero.
+ /// </summary>
+ /// <param name="blend">The <see cref="ColorBlend"/> object that defines the colors
+ /// and positions along the gradient.</param>
+ public Fill( ColorBlend blend ) :
+ this( blend, 0.0F )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient multi-color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of many colors based on a <see cref="ColorBlend"/> object, drawn at the
+ /// specified angle (degrees).
+ /// </summary>
+ /// <param name="blend">The <see cref="ColorBlend"/> object that defines the colors
+ /// and positions along the gradient.</param>
+ /// <param name="angle">The angle (degrees) of the gradient fill</param>
+ public Fill( ColorBlend blend, float angle )
+ {
+ Init();
+ _type = FillType.Brush;
+ this.CreateBrushFromBlend( blend, angle );
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient multi-color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of many colors based on an array of <see cref="Color"/> objects, drawn at an
+ /// angle of zero (degrees). The <see paramref="colors"/> array is used to create
+ /// a <see cref="ColorBlend"/> object assuming a even linear distribution of the colors
+ /// across the gradient.
+ /// </summary>
+ /// <param name="colors">The array of <see cref="Color"/> objects that defines the colors
+ /// along the gradient.</param>
+ public Fill( Color[] colors ) :
+ this( colors, 0.0F )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient multi-color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of many colors based on an array of <see cref="Color"/> objects, drawn at the
+ /// specified angle (degrees). The <see paramref="colors"/> array is used to create
+ /// a <see cref="ColorBlend"/> object assuming a even linear distribution of the colors
+ /// across the gradient.
+ /// </summary>
+ /// <param name="colors">The array of <see cref="Color"/> objects that defines the colors
+ /// along the gradient.</param>
+ /// <param name="angle">The angle (degrees) of the gradient fill</param>
+ public Fill( Color[] colors, float angle )
+ {
+ Init();
+ _color = colors[ colors.Length - 1 ];
+
+ ColorBlend blend = new ColorBlend();
+ blend.Colors = colors;
+ blend.Positions = new float[colors.Length];
+ blend.Positions[0] = 0.0F;
+ for ( int i=1; i<colors.Length; i++ )
+ blend.Positions[i] = (float) i / (float)( colors.Length - 1 );
+ _type = FillType.Brush;
+
+ this.CreateBrushFromBlend( blend, angle );
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient multi-color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of many colors based on an array of <see cref="Color"/> objects, drawn at the
+ /// an angle of zero (degrees). The <see paramref="colors"/> array is used to create
+ /// a <see cref="ColorBlend"/> object assuming a even linear distribution of the colors
+ /// across the gradient.
+ /// </summary>
+ /// <param name="colors">The array of <see cref="Color"/> objects that defines the colors
+ /// along the gradient.</param>
+ /// <param name="positions">The array of floating point values that defines the color
+ /// positions along the gradient. Values should range from 0 to 1.</param>
+ public Fill( Color[] colors, float[] positions ) :
+ this( colors, positions, 0.0F )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a linear gradient multi-color-fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> using the specified colors. This gradient fill
+ /// consists of many colors based on an array of <see cref="Color"/> objects, drawn at the
+ /// specified angle (degrees). The <see paramref="colors"/> array is used to create
+ /// a <see cref="ColorBlend"/> object assuming a even linear distribution of the colors
+ /// across the gradient.
+ /// </summary>
+ /// <param name="colors">The array of <see cref="Color"/> objects that defines the colors
+ /// along the gradient.</param>
+ /// <param name="positions">The array of floating point values that defines the color
+ /// positions along the gradient. Values should range from 0 to 1.</param>
+ /// <param name="angle">The angle (degrees) of the gradient fill</param>
+ public Fill( Color[] colors, float[] positions, float angle )
+ {
+ Init();
+ _color = colors[ colors.Length - 1 ];
+
+ ColorBlend blend = new ColorBlend();
+ blend.Colors = colors;
+ blend.Positions = positions;
+ _type = FillType.Brush;
+
+ this.CreateBrushFromBlend( blend, angle );
+ }
+
+ /// <summary>
+ /// Constructor that creates a texture fill, setting <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/> and using the specified image.
+ /// </summary>
+ /// <param name="image">The <see cref="Image"/> to use for filling</param>
+ /// <param name="wrapMode">The <see cref="WrapMode"/> class that controls the image wrapping properties</param>
+ public Fill( Image image, WrapMode wrapMode )
+ {
+ Init();
+ _color = Color.White;
+ _brush = new TextureBrush( image, wrapMode );
+ _type = FillType.Brush;
+ _image = image;
+ _wrapMode = wrapMode;
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="Brush"/> fill, using a user-supplied, custom
+ /// <see cref="Brush"/>. The brush will be scaled to fit the destination screen object
+ /// unless you manually change <see cref="IsScaled"/> to false;
+ /// </summary>
+ /// <param name="brush">The <see cref="Brush"/> to use for fancy fills. Typically, this would
+ /// be a <see cref="LinearGradientBrush"/> or a <see cref="TextureBrush"/> class</param>
+ public Fill( Brush brush ) : this( brush, Default.IsScaled )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="Brush"/> fill, using a user-supplied, custom
+ /// <see cref="Brush"/>. The brush will be scaled to fit the destination screen object
+ /// according to the <see paramref="isScaled"/> parameter.
+ /// </summary>
+ /// <param name="brush">The <see cref="Brush"/> to use for fancy fills. Typically, this would
+ /// be a <see cref="LinearGradientBrush"/> or a <see cref="TextureBrush"/> class</param>
+ /// <param name="isScaled">Determines if the brush will be scaled to fit the bounding box
+ /// of the destination object. true to scale it, false to leave it unscaled</param>
+ public Fill( Brush brush, bool isScaled )
+ {
+ Init();
+ _isScaled = isScaled;
+ _color = Color.White;
+ _brush = (Brush) brush.Clone();
+ _type = FillType.Brush;
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="Brush"/> fill, using a user-supplied, custom
+ /// <see cref="Brush"/>. This constructor will make the brush unscaled (see <see cref="IsScaled"/>),
+ /// but it provides <see paramref="alignH"/> and <see paramref="alignV"/> parameters to control
+ /// alignment of the brush with respect to the filled object.
+ /// </summary>
+ /// <param name="brush">The <see cref="Brush"/> to use for fancy fills. Typically, this would
+ /// be a <see cref="LinearGradientBrush"/> or a <see cref="TextureBrush"/> class</param>
+ /// <param name="alignH">Controls the horizontal alignment of the brush within the filled object
+ /// (see <see cref="AlignH"/></param>
+ /// <param name="alignV">Controls the vertical alignment of the brush within the filled object
+ /// (see <see cref="AlignV"/></param>
+ public Fill( Brush brush, AlignH alignH, AlignV alignV )
+ {
+ Init();
+ _alignH = alignH;
+ _alignV = alignV;
+ _isScaled = false;
+ _color = Color.White;
+ _brush = (Brush) brush.Clone();
+ _type = FillType.Brush;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The Fill object from which to copy</param>
+ public Fill( Fill rhs )
+ {
+ _color = rhs._color;
+ _secondaryValueGradientColor = rhs._color;
+
+ if ( rhs._brush != null )
+ _brush = (Brush) rhs._brush.Clone();
+ else
+ _brush = null;
+ _type = rhs._type;
+ _alignH = rhs.AlignH;
+ _alignV = rhs.AlignV;
+ _isScaled = rhs.IsScaled;
+ _rangeMin = rhs._rangeMin;
+ _rangeMax = rhs._rangeMax;
+ _rangeDefault = rhs._rangeDefault;
+ _gradientBM = null;
+
+ if ( rhs._colorList != null )
+ _colorList = (Color[]) rhs._colorList.Clone();
+ else
+ _colorList = null;
+
+ if ( rhs._positionList != null )
+ {
+ _positionList = (float[]) rhs._positionList.Clone();
+ }
+ else
+ _positionList = null;
+
+ if ( rhs._image != null )
+ _image = (Image) rhs._image.Clone();
+ else
+ _image = null;
+
+ _angle = rhs._angle;
+ _wrapMode = rhs._wrapMode;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Fill Clone()
+ {
+ return new Fill( this );
+ }
+
+ private void CreateBrushFromBlend( ColorBlend blend, float angle )
+ {
+ _angle = angle;
+
+ _colorList = (Color[]) blend.Colors.Clone();
+ _positionList = (float[]) blend.Positions.Clone();
+
+ _brush = new LinearGradientBrush( new Rectangle( 0, 0, 100, 100 ),
+ Color.Red, Color.White, angle );
+ ((LinearGradientBrush)_brush).InterpolationColors = blend;
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+ // schema changed to 2 with addition of rangeDefault
+ // schema changed to 10 with version 5 refactor -- not backwards compatible
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Fill( SerializationInfo info, StreamingContext context )
+ {
+ Init();
+
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _color = (Color) info.GetValue( "color", typeof(Color) );
+ _secondaryValueGradientColor = (Color) info.GetValue( "secondaryValueGradientColor", typeof( Color ) );
+ //brush = (Brush) info.GetValue( "brush", typeof(Brush) );
+ //brushHolder = (BrushHolder) info.GetValue( "brushHolder", typeof(BrushHolder) );
+ _type = (FillType) info.GetValue( "type", typeof(FillType) );
+ _isScaled = info.GetBoolean( "isScaled" );
+ _alignH = (AlignH) info.GetValue( "alignH", typeof(AlignH) );
+ _alignV = (AlignV) info.GetValue( "alignV", typeof(AlignV) );
+ _rangeMin = info.GetDouble( "rangeMin" );
+ _rangeMax = info.GetDouble( "rangeMax" );
+
+ //BrushHolder brushHolder = (BrushHolder) info.GetValue( "brushHolder", typeof( BrushHolder ) );
+ //brush = brush;
+
+ _colorList = (Color[]) info.GetValue( "colorList", typeof(Color[]) );
+ _positionList = (float[]) info.GetValue( "positionList", typeof(float[]) );
+ _angle = info.GetSingle( "angle" );
+ _image = (Image) info.GetValue( "image", typeof(Image) );
+ _wrapMode = (WrapMode) info.GetValue( "wrapMode", typeof(WrapMode) );
+
+ if ( _colorList != null && _positionList != null )
+ {
+ ColorBlend blend = new ColorBlend();
+ blend.Colors = _colorList;
+ blend.Positions = _positionList;
+ CreateBrushFromBlend( blend, _angle );
+ }
+ else if ( _image != null )
+ {
+ _brush = new TextureBrush( _image, _wrapMode );
+ }
+
+ _rangeDefault = info.GetDouble( "rangeDefault" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+
+ info.AddValue( "schema", schema );
+ info.AddValue( "color", _color );
+ info.AddValue( "secondaryValueGradientColor", _secondaryValueGradientColor );
+ //info.AddValue( "brush", brush );
+ //info.AddValue( "brushHolder", brushHolder );
+ info.AddValue( "type", _type );
+ info.AddValue( "isScaled", _isScaled );
+ info.AddValue( "alignH", _alignH );
+ info.AddValue( "alignV", _alignV );
+ info.AddValue( "rangeMin", _rangeMin );
+ info.AddValue( "rangeMax", _rangeMax );
+
+ //BrushHolder brushHolder = new BrushHolder();
+ //brush = brush;
+ //info.AddValue( "brushHolder", brushHolder );
+
+ info.AddValue( "colorList", _colorList );
+ info.AddValue( "positionList", _positionList );
+ info.AddValue( "angle", _angle );
+ info.AddValue( "image", _image );
+ info.AddValue( "wrapMode", _wrapMode );
+
+ info.AddValue( "rangeDefault", _rangeDefault );
+ }
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// The fill color. This property is used as a single color to make a solid fill
+ /// (<see cref="Type"/> is <see cref="FillType.Solid"/>), or it can be used in
+ /// combination with <see cref="System.Drawing.Color.White"/> to make a
+ /// <see cref="LinearGradientBrush"/>
+ /// when <see cref="Type"/> is <see cref="FillType.Brush"/> and <see cref="Brush"/>
+ /// is null.
+ /// </summary>
+ /// <seealso cref="Type"/>
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the secondary color for gradientByValue fills.
+ /// </summary>
+ /// <remarks>
+ /// This property is only applicable if the <see cref="Type"/> is
+ /// <see cref="ZedGraph.FillType.GradientByX"/>,
+ /// <see cref="ZedGraph.FillType.GradientByY"/>, or
+ /// <see cref="ZedGraph.FillType.GradientByZ"/>. Once the gradient-by-value logic picks
+ /// a color, a new gradient will be created using the SecondaryValueGradientColor, the
+ /// resulting gradient-by-value color, and the angle setting for this
+ /// <see cref="Fill" />. Use a value of <see cref="System.Drawing.Color.Empty">Color.Empty</see> to have
+ /// a solid-color <see cref="Fill" /> resulting from a gradient-by-value
+ /// <see cref="FillType" />.
+ /// </remarks>
+ public Color SecondaryValueGradientColor
+ {
+ get { return _secondaryValueGradientColor; }
+ set { _secondaryValueGradientColor = value; }
+ }
+
+ /// <summary>
+ /// The custom fill brush. This can be a <see cref="SolidBrush"/>, a
+ /// <see cref="LinearGradientBrush"/>, or a <see cref="TextureBrush"/>. This property is
+ /// only applicable if the <see cref="Type"/> property is set
+ /// to <see cref="FillType.Brush"/>.
+ /// </summary>
+ public Brush Brush
+ {
+ get { return _brush; }
+ set { _brush = value; }
+ }
+ /// <summary>
+ /// Determines the type of fill, which can be either solid
+ /// color (<see cref="ZedGraph.FillType.Solid"/>) or a custom brush
+ /// (<see cref="ZedGraph.FillType.Brush"/>). See <see cref="Type"/> for
+ /// more information.
+ /// </summary>
+ /// <seealso cref="ZedGraph.Fill.Color"/>
+ public FillType Type
+ {
+ get { return _type; }
+ set { _type = value; }
+ }
+ /// <summary>
+ /// This property determines the type of color fill.
+ /// Returns true if the <see cref="Type"/> property is either
+ /// <see cref="FillType.Solid"/> or
+ /// <see cref="FillType.Brush"/>. If set to true, this property
+ /// will automatically set the <see cref="Type"/> to
+ /// <see cref="FillType.Brush"/>. If set to false, this property
+ /// will automatically set the <see cref="Type"/> to
+ /// <see cref="FillType.None"/>. In order to get a regular
+ /// solid-color fill, you have to manually set <see cref="Type"/>
+ /// to <see cref="FillType.Solid"/>.
+ /// </summary>
+ /// <seealso cref="Color"/>
+ /// <seealso cref="Brush"/>
+ /// <seealso cref="Type"/>
+ public bool IsVisible
+ {
+ get { return _type != FillType.None; }
+ set { _type = value ? ( _type == FillType.None ? FillType.Brush : _type ) : FillType.None; }
+ }
+
+ /// <summary>
+ /// Determines if the brush will be scaled to the bounding box
+ /// of the filled object. If this value is false, then the brush will only be aligned
+ /// with the filled object based on the <see cref="AlignH"/> and <see cref="AlignV"/>
+ /// properties.
+ /// </summary>
+ public bool IsScaled
+ {
+ get { return _isScaled; }
+ set { _isScaled = value; }
+ }
+
+ /// <summary>
+ /// Determines how the brush will be aligned with the filled object
+ /// in the horizontal direction. This value is a <see cref="ZedGraph.AlignH"/> enumeration.
+ /// This field only applies if <see cref="IsScaled"/> is false.
+ /// </summary>
+ /// <seealso cref="AlignV"/>
+ public AlignH AlignH
+ {
+ get { return _alignH; }
+ set { _alignH = value; }
+ }
+
+ /// <summary>
+ /// Determines how the brush will be aligned with the filled object
+ /// in the vertical direction. This value is a <see cref="ZedGraph.AlignV"/> enumeration.
+ /// This field only applies if <see cref="IsScaled"/> is false.
+ /// </summary>
+ /// <seealso cref="AlignH"/>
+ public AlignV AlignV
+ {
+ get { return _alignV; }
+ set { _alignV = value; }
+ }
+
+ /// <summary>
+ /// Returns a boolean value indicating whether or not this fill is a "Gradient-By-Value"
+ /// type. This is true for <see cref="FillType.GradientByX"/>, <see cref="FillType.GradientByY"/>,
+ /// or <see cref="FillType.GradientByZ"/>.
+ /// </summary>
+ /// <remarks>
+ /// The gradient by value fill method allows the fill color for each point or bar to
+ /// be based on a value for that point (either X, Y, or Z in the <see cref="IPointList"/>.
+ /// For example, assume a <see cref="Fill"/> class is defined with a linear gradient ranging from
+ /// <see cref="System.Drawing.Color.Blue"/> to <see cref="System.Drawing.Color.Red"/> and the <see cref="Fill.Type"/>
+ /// is set to <see cref="FillType.GradientByY"/>. If <see cref="RangeMin"/> is set to
+ /// 100.0 and <see cref="RangeMax"/> is set to 200.0, then a point that has a Y value of
+ /// 100 or less will be colored blue, a point with a Y value of 200 or more will be
+ /// colored red, and a point between 100 and 200 will have a color based on a linear scale
+ /// between blue and red. Note that the fill color is always solid for any given point.
+ /// You can use the Z value from <see cref="IPointList"/> along with
+ /// <see cref="FillType.GradientByZ"/> to color individual points according to some
+ /// property that is independent of the X,Y point pair.
+ /// </remarks>
+ /// <value>true if this is a Gradient-by-value type, false otherwise</value>
+ /// <seealso cref="FillType.GradientByX"/>
+ /// <seealso cref="FillType.GradientByY"/>
+ /// <seealso cref="FillType.GradientByZ"/>
+ public bool IsGradientValueType
+ {
+ get { return _type == FillType.GradientByX || _type == FillType.GradientByY ||
+ _type == FillType.GradientByZ || _type == FillType.GradientByColorValue; }
+ }
+
+ /// <summary>
+ /// The minimum user-scale value for the gradient-by-value determination. This defines
+ /// the user-scale value for the start of the gradient.
+ /// </summary>
+ /// <seealso cref="FillType.GradientByX"/>
+ /// <seealso cref="FillType.GradientByY"/>
+ /// <seealso cref="FillType.GradientByZ"/>
+ /// <seealso cref="IsGradientValueType"/>
+ /// <seealso cref="RangeMax"/>
+ /// <seealso cref="RangeDefault"/>
+ /// <value>A double value, in user scale unit</value>
+ public double RangeMin
+ {
+ get { return _rangeMin; }
+ set { _rangeMin = value; }
+ }
+ /// <summary>
+ /// The maximum user-scale value for the gradient-by-value determination. This defines
+ /// the user-scale value for the end of the gradient.
+ /// </summary>
+ /// <seealso cref="FillType.GradientByX"/>
+ /// <seealso cref="FillType.GradientByY"/>
+ /// <seealso cref="FillType.GradientByZ"/>
+ /// <seealso cref="IsGradientValueType"/>
+ /// <seealso cref="RangeMin"/>
+ /// <seealso cref="RangeDefault"/>
+ /// <value>A double value, in user scale unit</value>
+ public double RangeMax
+ {
+ get { return _rangeMax; }
+ set { _rangeMax = value; }
+ }
+
+ /// <summary>
+ /// The default user-scale value for the gradient-by-value determination. This defines the
+ /// value that will be used when there is no point value available, or the actual point value
+ /// is invalid.
+ /// </summary>
+ /// <remarks>
+ /// Note that this value, when defined, will determine the color that is used in the legend.
+ /// If this value is set to double.MaxValue, then it remains "undefined." In this case, the
+ /// legend symbols will actually be filled with a color gradient representing the range of
+ /// colors.
+ /// </remarks>
+ /// <seealso cref="FillType.GradientByX"/>
+ /// <seealso cref="FillType.GradientByY"/>
+ /// <seealso cref="FillType.GradientByZ"/>
+ /// <seealso cref="IsGradientValueType"/>
+ /// <seealso cref="RangeMin"/>
+ /// <seealso cref="RangeMax"/>
+ /// <value>A double value, in user scale unit</value>
+ public double RangeDefault
+ {
+ get { return _rangeDefault; }
+ set { _rangeDefault = value; }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Create a fill brush using current properties. This method will construct a brush based on the
+ /// settings of <see cref="ZedGraph.Fill.Type"/>, <see cref="ZedGraph.Fill.Color"/>
+ /// and <see cref="ZedGraph.Fill.Brush"/>. If
+ /// <see cref="ZedGraph.Fill.Type"/> is set to <see cref="ZedGraph.FillType.Brush"/> and
+ /// <see cref="ZedGraph.Fill.Brush"/>
+ /// is null, then a <see cref="LinearGradientBrush"/> will be created between the colors of
+ /// <see cref="System.Drawing.Color.White"/> and <see cref="ZedGraph.Fill.Color"/>.
+ /// </summary>
+ /// <param name="rect">A rectangle that bounds the object to be filled. This determines
+ /// the start and end of the gradient fill.</param>
+ /// <returns>A <see cref="System.Drawing.Brush"/> class representing the fill brush</returns>
+ public Brush MakeBrush( RectangleF rect )
+ {
+ // just provide a default value for the valueFraction
+ // return MakeBrush( rect, new PointPair( 0.5, 0.5, 0.5 ) );
+ return MakeBrush( rect, null );
+ }
+
+ /// <summary>
+ /// Create a fill brush using current properties. This method will construct a brush based on the
+ /// settings of <see cref="ZedGraph.Fill.Type"/>, <see cref="ZedGraph.Fill.Color"/>
+ /// and <see cref="ZedGraph.Fill.Brush"/>. If
+ /// <see cref="ZedGraph.Fill.Type"/> is set to <see cref="ZedGraph.FillType.Brush"/> and
+ /// <see cref="ZedGraph.Fill.Brush"/>
+ /// is null, then a <see cref="LinearGradientBrush"/> will be created between the colors of
+ /// <see cref="System.Drawing.Color.White"/> and <see cref="ZedGraph.Fill.Color"/>.
+ /// </summary>
+ /// <param name="rect">A rectangle that bounds the object to be filled. This determines
+ /// the start and end of the gradient fill.</param>
+ /// <param name="dataValue">The data value to be used for a value-based
+ /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>,
+ /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param>
+ /// <returns>A <see cref="System.Drawing.Brush"/> class representing the fill brush</returns>
+ public Brush MakeBrush( RectangleF rect, PointPair dataValue )
+ {
+ // get a brush
+ if ( this.IsVisible && ( !_color.IsEmpty || _brush != null ) )
+ {
+ if ( rect.Height < 1.0F )
+ rect.Height = 1.0F;
+ if ( rect.Width < 1.0F )
+ rect.Width = 1.0F;
+
+ //Brush brush;
+ if ( _type == FillType.Brush )
+ {
+ return ScaleBrush( rect, _brush, _isScaled );
+ }
+ else if ( IsGradientValueType )
+ {
+ if ( dataValue != null )
+ {
+ if ( !_secondaryValueGradientColor.IsEmpty )
+ {
+ // Go ahead and create a new Fill so we can do all the scaling, etc.,
+ // that is associated with a gradient
+ Fill tmpFill = new Fill( _secondaryValueGradientColor,
+ GetGradientColor( dataValue ), _angle );
+ return tmpFill.MakeBrush( rect );
+ }
+ else
+ return new SolidBrush( GetGradientColor( dataValue ) );
+ }
+ else if ( _rangeDefault != double.MaxValue )
+ {
+ if ( !_secondaryValueGradientColor.IsEmpty )
+ {
+ // Go ahead and create a new Fill so we can do all the scaling, etc.,
+ // that is associated with a gradient
+ Fill tmpFill = new Fill( _secondaryValueGradientColor,
+ GetGradientColor( _rangeDefault ), _angle );
+ return tmpFill.MakeBrush( rect );
+ }
+ else
+ return new SolidBrush( GetGradientColor( _rangeDefault ) );
+ }
+ else
+ return ScaleBrush( rect, _brush, true );
+ }
+ else
+ return new SolidBrush( _color );
+ }
+
+ // Always return a suitable default
+ return new SolidBrush( Color.White );
+ }
+
+ internal Color GetGradientColor( PointPair dataValue )
+ {
+ double val;
+
+ if ( dataValue == null )
+ val = _rangeDefault;
+ else if ( _type == FillType.GradientByColorValue )
+ val = dataValue.ColorValue;
+ else if ( _type == FillType.GradientByZ )
+ val = dataValue.Z;
+ else if ( _type == FillType.GradientByY )
+ val = dataValue.Y;
+ else
+ val = dataValue.X;
+
+ return GetGradientColor( val );
+ }
+
+ internal Color GetGradientColor( double val )
+ {
+ double valueFraction;
+
+ if ( Double.IsInfinity( val ) || double.IsNaN( val ) || val == PointPair.Missing )
+ val = _rangeDefault;
+
+ if ( _rangeMax - _rangeMin < 1e-20 || val == double.MaxValue )
+ valueFraction = 0.5;
+ else
+ valueFraction = ( val - _rangeMin ) / ( _rangeMax - _rangeMin );
+
+ if ( valueFraction < 0.0 )
+ valueFraction = 0.0;
+ else if ( valueFraction > 1.0 )
+ valueFraction = 1.0;
+
+ if ( _gradientBM == null )
+ {
+ RectangleF rect = new RectangleF( 0, 0, 100, 1 );
+ _gradientBM = new Bitmap( 100, 1 );
+ Graphics gBM = Graphics.FromImage( _gradientBM );
+
+ Brush tmpBrush = ScaleBrush( rect, _brush, true );
+ gBM.FillRectangle( tmpBrush, rect );
+ }
+
+ return _gradientBM.GetPixel( (int) (99.9 * valueFraction), 0 );
+ }
+
+ private Brush ScaleBrush( RectangleF rect, Brush brush, bool isScaled )
+ {
+ if ( brush != null )
+ {
+ if ( brush is SolidBrush )
+ {
+ return (Brush) brush.Clone();
+ }
+ else if ( brush is LinearGradientBrush )
+ {
+ LinearGradientBrush linBrush = (LinearGradientBrush) brush.Clone();
+
+ if ( isScaled )
+ {
+ linBrush.ScaleTransform( rect.Width / linBrush.Rectangle.Width,
+ rect.Height / linBrush.Rectangle.Height, MatrixOrder.Append );
+ linBrush.TranslateTransform( rect.Left - linBrush.Rectangle.Left,
+ rect.Top - linBrush.Rectangle.Top, MatrixOrder.Append );
+ }
+ else
+ {
+ float dx = 0,
+ dy = 0;
+ switch ( _alignH )
+ {
+ case AlignH.Left:
+ dx = rect.Left - linBrush.Rectangle.Left;
+ break;
+ case AlignH.Center:
+ dx = ( rect.Left + rect.Width / 2.0F ) - linBrush.Rectangle.Left;
+ break;
+ case AlignH.Right:
+ dx = ( rect.Left + rect.Width ) - linBrush.Rectangle.Left;
+ break;
+ }
+
+ switch ( _alignV )
+ {
+ case AlignV.Top:
+ dy = rect.Top - linBrush.Rectangle.Top;
+ break;
+ case AlignV.Center:
+ dy = ( rect.Top + rect.Height / 2.0F ) - linBrush.Rectangle.Top;
+ break;
+ case AlignV.Bottom:
+ dy = ( rect.Top + rect.Height) - linBrush.Rectangle.Top;
+ break;
+ }
+
+ linBrush.TranslateTransform( dx, dy, MatrixOrder.Append );
+ }
+
+ return linBrush;
+
+ } // LinearGradientBrush
+ else if ( brush is TextureBrush )
+ {
+ TextureBrush texBrush = (TextureBrush) brush.Clone();
+
+ if ( isScaled )
+ {
+ texBrush.ScaleTransform( rect.Width / texBrush.Image.Width,
+ rect.Height / texBrush.Image.Height, MatrixOrder.Append );
+ texBrush.TranslateTransform( rect.Left, rect.Top, MatrixOrder.Append );
+ }
+ else
+ {
+ float dx = 0,
+ dy = 0;
+ switch ( _alignH )
+ {
+ case AlignH.Left:
+ dx = rect.Left;
+ break;
+ case AlignH.Center:
+ dx = ( rect.Left + rect.Width / 2.0F );
+ break;
+ case AlignH.Right:
+ dx = ( rect.Left + rect.Width );
+ break;
+ }
+
+ switch ( _alignV )
+ {
+ case AlignV.Top:
+ dy = rect.Top;
+ break;
+ case AlignV.Center:
+ dy = ( rect.Top + rect.Height / 2.0F );
+ break;
+ case AlignV.Bottom:
+ dy = ( rect.Top + rect.Height);
+ break;
+ }
+
+ texBrush.TranslateTransform( dx, dy, MatrixOrder.Append );
+ }
+
+ return texBrush;
+ }
+ else // other brush type
+ {
+ return (Brush) brush.Clone();
+ }
+ }
+ else
+ // If they didn't provide a brush, make one using the fillcolor gradient to white
+ return new LinearGradientBrush( rect, Color.White, _color, 0F );
+ }
+
+ /// <summary>
+ /// Fill the background of the <see cref="RectangleF"/> area, using the
+ /// fill type from this <see cref="Fill"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct specifying the area
+ /// to be filled</param>
+ public void Draw( Graphics g, RectangleF rect )
+ {
+ Draw( g, rect, null );
+ /*
+ if ( this.IsVisible )
+ {
+ using( Brush brush = this.MakeBrush( rect ) )
+ {
+ g.FillRectangle( brush, rect );
+ //brush.Dispose();
+ }
+ }
+ */
+ }
+
+ /// <summary>
+ /// Fill the background of the <see cref="RectangleF"/> area, using the
+ /// fill type from this <see cref="Fill"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct specifying the area
+ /// to be filled</param>
+ /// <param name="pt">The data value to be used in case it's a
+ /// <see cref="FillType.GradientByX" />, <see cref="FillType.GradientByY" />, or
+ /// <see cref="FillType.GradientByZ" /> <see cref="FillType" />.</param>
+ public void Draw( Graphics g, RectangleF rect, PointPair pt )
+ {
+ if ( this.IsVisible )
+ {
+ using ( Brush brush = this.MakeBrush( rect, pt ) )
+ {
+ g.FillRectangle( brush, rect );
+ }
+ }
+ }
+
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/FilteredPointList.cs b/ZedGraph/FilteredPointList.cs
new file mode 100644
index 0000000..f42e4cc
--- /dev/null
+++ b/ZedGraph/FilteredPointList.cs
@@ -0,0 +1,321 @@
+//============================================================================
+//FilteredPointList class
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================using System;
+using System;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An example of an <see cref="IPointList" /> implementation that stores large datasets, and
+ /// selectively filters the output data depending on the displayed range.
+ /// </summary>
+ /// <remarks>
+ /// This class will refilter the data points each time <see cref="SetBounds" /> is called. The
+ /// data are filtered down to <see cref="MaxPts" /> points, within the data bounds of
+ /// a minimum and maximum data range. The data are filtered by simply skipping
+ /// points to achieve the desired total number of points. Input arrays are assumed to be
+ /// monotonically increasing in X, and evenly spaced in X.
+ /// </remarks>
+ /// <seealso cref="PointPairList" />
+ /// <seealso cref="BasicArrayPointList" />
+ /// <seealso cref="IPointList" />
+ /// <seealso cref="IPointListEdit" />
+ ///
+ /// <author> John Champion with mods by Christophe Holmes</author>
+ /// <version> $Revision: 1.11 $ $Date: 2007-11-29 02:15:39 $ </version>
+ [Serializable]
+ public class FilteredPointList : IPointList
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// Instance of an array of x values
+ /// </summary>
+ private double[] _x;
+ /// <summary>
+ /// Instance of an array of x values
+ /// </summary>
+ private double[] _y;
+ /*
+ /// <summary>
+ /// This is the minimum value of the range of interest (typically the minimum of
+ /// the range that you have zoomed into)
+ /// </summary>
+ //private double _xMinBound = double.MinValue;
+ /// <summary>
+ /// This is the maximum value of the range of interest (typically the maximum of
+ /// the range that you have zoomed into)
+ /// </summary>
+ //private double _xMaxBound = double.MaxValue;
+ */
+ /// <summary>
+ /// This is the maximum number of points that you want to see in the filtered dataset
+ /// </summary>
+ private int _maxPts = -1;
+
+ /// <summary>
+ /// The index of the xMinBound above
+ /// </summary>
+ private int _minBoundIndex = -1;
+ /// <summary>
+ /// The index of the xMaxBound above
+ /// </summary>
+ private int _maxBoundIndex = -1;
+
+// /// <summary>
+// /// Switch used to indicate if the next filtered point should be the high point or the
+// /// low point within the current range.
+// /// </summary>
+// private bool _upDown = false;
+
+// /// <summary>
+// /// Determines if the high/low logic will be used.
+// /// </summary>
+// private bool _isApplyHighLowLogic = true;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="PointPair"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <remarks>
+ /// Returns <see cref="PointPairBase.Missing" /> for any value of <see paramref="index" />
+ /// that is outside of its corresponding array bounds.
+ /// </remarks>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="PointPair"/> object to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object reference.</value>
+ public PointPair this[ int index ]
+ {
+ get
+ {
+ // See if the array should be bounded
+ if ( _minBoundIndex >= 0 && _maxBoundIndex >= 0 && _maxPts >= 0 )
+ {
+ // get number of points in bounded range
+ int nPts = _maxBoundIndex - _minBoundIndex + 1;
+
+ if ( nPts > _maxPts )
+ {
+ // if we're skipping points, then calculate the new index
+ index = _minBoundIndex + (int) ( (double) index * (double) nPts / (double) _maxPts );
+ }
+ else
+ {
+ // otherwise, index is just offset by the start of the bounded range
+ index += _minBoundIndex;
+ }
+ }
+
+ double xVal, yVal;
+ if ( index >= 0 && index < _x.Length )
+ xVal = _x[index];
+ else
+ xVal = PointPair.Missing;
+
+ if ( index >= 0 && index < _y.Length )
+ yVal = _y[index];
+ else
+ yVal = PointPair.Missing;
+
+
+
+ return new PointPair( xVal, yVal, PointPair.Missing, null );
+ }
+
+ set
+ {
+ // See if the array should be bounded
+ if ( _minBoundIndex >= 0 && _maxBoundIndex >= 0 && _maxPts >= 0 )
+ {
+ // get number of points in bounded range
+ int nPts = _maxBoundIndex - _minBoundIndex + 1;
+
+ if ( nPts > _maxPts )
+ {
+ // if we're skipping points, then calculate the new index
+ index = _minBoundIndex + (int) ( (double) index * (double) nPts / (double) _maxPts );
+ }
+ else
+ {
+ // otherwise, index is just offset by the start of the bounded range
+ index += _minBoundIndex;
+ }
+ }
+
+ if ( index >= 0 && index < _x.Length )
+ _x[index] = value.X;
+
+ if ( index >= 0 && index < _y.Length )
+ _y[index] = value.Y;
+ }
+ }
+
+ /// <summary>
+ /// Returns the number of points according to the current state of the filter.
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ int arraySize = _x.Length;
+
+ // Is the filter active?
+ if ( _minBoundIndex >= 0 && _maxBoundIndex >= 0 && _maxPts > 0 )
+ {
+ // get the number of points within the filter bounds
+ int boundSize = _maxBoundIndex - _minBoundIndex + 1;
+
+ // limit the point count to the filter bounds
+ if ( boundSize < arraySize )
+ arraySize = boundSize;
+
+ // limit the point count to the declared max points
+ if ( arraySize > _maxPts )
+ arraySize = _maxPts;
+ }
+
+ return arraySize;
+ }
+ }
+
+ /// <summary>
+ /// Gets the desired number of filtered points to output. You can set this value by
+ /// calling <see cref="SetBounds" />.
+ /// </summary>
+ public int MaxPts
+ {
+ get { return _maxPts; }
+ }
+
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to initialize the PointPairList from two arrays of
+ /// type double.
+ /// </summary>
+ public FilteredPointList( double[] x, double[] y )
+ {
+ _x = x;
+ _y = y;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The FilteredPointList from which to copy</param>
+ public FilteredPointList( FilteredPointList rhs )
+ {
+ _x = (double[]) rhs._x.Clone();
+ _y = (double[]) rhs._y.Clone();
+ _minBoundIndex = rhs._minBoundIndex;
+ _maxBoundIndex = rhs._maxBoundIndex;
+ _maxPts = rhs._maxPts;
+
+ }
+
+ /// <summary>
+ /// Deep-copy clone routine
+ /// </summary>
+ /// <returns>A new, independent copy of the FilteredPointList</returns>
+ virtual public object Clone()
+ {
+ return new FilteredPointList( this );
+ }
+
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Set the data bounds to the specified minimum, maximum, and point count. Use values of
+ /// min=double.MinValue and max=double.MaxValue to get the full range of data. Use maxPts=-1
+ /// to not limit the number of points. Call this method anytime the zoom range is changed.
+ /// </summary>
+ /// <param name="min">The lower bound for the X data of interest</param>
+ /// <param name="max">The upper bound for the X data of interest</param>
+ /// <param name="maxPts">The maximum number of points allowed to be
+ /// output by the filter</param>
+ // New code mods by ingineer
+ public void SetBounds( double min, double max, int maxPts )
+ {
+ _maxPts = maxPts;
+
+ // find the index of the start and end of the bounded range
+ int first = Array.BinarySearch( _x, min );
+ int last = Array.BinarySearch( _x, max );
+
+ // Make sure the bounded indices are legitimate
+ // if BinarySearch() doesn't find the value, it returns the bitwise
+ // complement of the index of the 1st element larger than the sought value
+
+ if (first < 0)
+ {
+ if (first == -1)
+ first = 0;
+ else
+ first = ~(first + 1);
+ }
+
+ if ( last < 0 )
+ last = ~last;
+
+ _minBoundIndex = first;
+ _maxBoundIndex = last;
+ }
+
+ // The old version, as of 21-Oct-2007
+ //public void SetBounds2(double min, double max, int maxPts)
+ //{
+ // _maxPts = maxPts;
+
+ // // assume data points are equally spaced, and calculate the X step size between
+ // // each data point
+ // double step = (_x[_x.Length - 1] - _x[0]) / (double)_x.Length;
+
+ // if (min < _x[0])
+ // min = _x[0];
+ // if (max > _x[_x.Length - 1])
+ // max = _x[_x.Length - 1];
+
+ // // calculate the index of the start of the bounded range
+ // int first = (int)((min - _x[0]) / step);
+
+ // // calculate the index of the last point of the bounded range
+ // int last = (int)((max - min) / step + first);
+
+ // // Make sure the bounded indices are legitimate
+ // first = Math.Max(Math.Min(first, _x.Length), 0);
+ // last = Math.Max(Math.Min(last, _x.Length), 0);
+
+ // _minBoundIndex = first;
+ // _maxBoundIndex = last;
+ //}
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/FontSpec.cs b/ZedGraph/FontSpec.cs
new file mode 100644
index 0000000..b188740
--- /dev/null
+++ b/ZedGraph/FontSpec.cs
@@ -0,0 +1,1502 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The <see cref="FontSpec"/> class is a generic font class that maintains the font family,
+ /// attributes, colors, border and fill modes, font size, and angle information.
+ /// This class can render text with a variety of alignment options using the
+ /// <see cref="AlignH"/> and <see cref="AlignV"/> parameters in the
+ /// <see cref="Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.24 $ $Date: 2007-01-25 07:56:08 $ </version>
+ [Serializable]
+ public class FontSpec : ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores the color of the font characters for this
+ /// <see cref="FontSpec"/>. Use the public property <see cref="FontColor"/>
+ /// to access this value.
+ /// </summary>
+ /// <value>A system <see cref="System.Drawing.Color"/> reference.</value>
+ private Color _fontColor;
+ /// <summary>
+ /// Private field that stores the font family name for this <see cref="FontSpec"/>.
+ /// Use the public property <see cref="Family"/> to access this value.
+ /// </summary>
+ /// <value>A text string with the font family name, e.g., "Arial"</value>
+ private string _family;
+ /// <summary>
+ /// Private field that determines whether this <see cref="FontSpec"/> is
+ /// drawn with bold typeface.
+ /// Use the public property <see cref="IsBold"/> to access this value.
+ /// </summary>
+ /// <value>A boolean value, true for bold, false for normal</value>
+ private bool _isBold;
+ /// <summary>
+ /// Private field that determines whether this <see cref="FontSpec"/> is
+ /// drawn with italic typeface.
+ /// Use the public property <see cref="IsItalic"/> to access this value.
+ /// </summary>
+ /// <value>A boolean value, true for italic, false for normal</value>
+ private bool _isItalic;
+ /// <summary>
+ /// Private field that determines whether this <see cref="FontSpec"/> is
+ /// drawn with underlined typeface.
+ /// Use the public property <see cref="IsUnderline"/> to access this value.
+ /// </summary>
+ /// <value>A boolean value, true for underline, false for normal</value>
+ private bool _isUnderline;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="FontSpec"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+ /// <summary>
+ /// Private field that determines the properties of the border around the text.
+ /// Use the public property <see cref="Border"/> to access this value.
+ /// </summary>
+ private Border _border;
+
+ /// <summary>
+ /// Private field that determines the angle at which this
+ /// <see cref="FontSpec"/> object is drawn. Use the public property
+ /// <see cref="Angle"/> to access this value.
+ /// </summary>
+ /// <value>The angle of the font, measured in anti-clockwise degrees from
+ /// horizontal. Negative values are permitted.</value>
+ private float _angle;
+
+ /// <summary>
+ /// Private field that determines the alignment with which this
+ /// <see cref="FontSpec"/> object is drawn. This alignment really only
+ /// affects multi-line strings. Use the public property
+ /// <see cref="StringAlignment"/> to access this value.
+ /// </summary>
+ /// <value>A <see cref="StringAlignment"/> enumeration.</value>
+ private StringAlignment _stringAlignment;
+
+ /// <summary>
+ /// Private field that determines the size of the font for this
+ /// <see cref="FontSpec"/> object. Use the public property
+ /// <see cref="Size"/> to access this value.
+ /// </summary>
+ /// <value>The size of the font, measured in points (1/72 inch).</value>
+ private float _size;
+
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="Font"/>
+ /// object for this <see cref="FontSpec"/>. This font object will be at
+ /// the actual drawn size <see cref="_scaledSize"/> according to the current
+ /// size of the <see cref="GraphPane"/>. Use the public method
+ /// <see cref="GetFont"/> to access this font object.
+ /// </summary>
+ /// <value>A reference to a <see cref="Font"/> object</value>
+ private Font _font;
+
+ /// <summary>
+ /// Private field that determines if the <see cref="FontSpec" /> will be
+ /// displayed using anti-aliasing logic.
+ /// Use the public property <see cref="IsAntiAlias" /> to access this value.
+ /// </summary>
+ private bool _isAntiAlias;
+ /// <summary>
+ /// Private field that determines if the <see cref="FontSpec" /> will be
+ /// displayed with a drop shadow.
+ /// Use the public property <see cref="IsDropShadow" /> to access this value.
+ /// </summary>
+ private bool _isDropShadow;
+ /// <summary>
+ /// Private field that determines the color of the dropshadow for this
+ /// <see cref="FontSpec" />.
+ /// Use the public property <see cref="DropShadowColor" /> to access this value.
+ /// </summary>
+ private Color _dropShadowColor;
+ /// <summary>
+ /// Private field that determines the offset angle of the dropshadow for this
+ /// <see cref="FontSpec" />.
+ /// Use the public property <see cref="DropShadowAngle" /> to access this value.
+ /// </summary>
+ private float _dropShadowAngle;
+ /// <summary>
+ /// Private field that determines the offset distance of the dropshadow for this
+ /// <see cref="FontSpec" />.
+ /// Use the public property <see cref="DropShadowOffset" /> to access this value.
+ /// </summary>
+ private float _dropShadowOffset;
+
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="Font"/>
+ /// object that will be used for superscripts. This font object will be a
+ /// fraction of the <see cref="FontSpec"/> <see cref="_scaledSize"/>,
+ /// based on the value of <see cref="Default.SuperSize"/>. This
+ /// property is internal, and has no public access.
+ /// </summary>
+ /// <value>A reference to a <see cref="Font"/> object</value>
+ private Font _superScriptFont;
+
+ /// <summary>
+ /// Private field that temporarily stores the scaled size of the font for this
+ /// <see cref="FontSpec"/> object. This represents the actual on-screen
+ /// size, rather than the <see cref="Size"/> that represents the reference
+ /// size for a "full-sized" <see cref="GraphPane"/>.
+ /// </summary>
+ /// <value>The size of the font, measured in points (1/72 inch).</value>
+ private float _scaledSize;
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="FontSpec"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default size fraction of the superscript font, expressed as a fraction
+ /// of the size of the main font.
+ /// </summary>
+ public static float SuperSize = 0.85F;
+ /// <summary>
+ /// The default shift fraction of the superscript, expressed as a
+ /// fraction of the superscripted character height. This is the height
+ /// above the main font (a zero shift means the main font and the superscript
+ /// font have the tops aligned).
+ /// </summary>
+ public static float SuperShift = 0.4F;
+ /// <summary>
+ /// The default color for filling in the background of the text block
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.White;
+ /// <summary>
+ /// The default custom brush for filling in this <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null;
+ /// <summary>
+ /// The default fill mode for this <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FillType = FillType.Solid;
+ /// <summary>
+ /// Default value for the alignment with which this
+ /// <see cref="FontSpec"/> object is drawn. This alignment really only
+ /// affects multi-line strings.
+ /// </summary>
+ /// <value>A <see cref="StringAlignment"/> enumeration.</value>
+ public static StringAlignment StringAlignment = StringAlignment.Center;
+
+ /// <summary>
+ /// Default value for <see cref="FontSpec.IsDropShadow"/>, which determines
+ /// if the drop shadow is displayed for this <see cref="FontSpec" />.
+ /// </summary>
+ public static bool IsDropShadow = false;
+ /// <summary>
+ /// Default value for <see cref="FontSpec.IsAntiAlias"/>, which determines
+ /// if anti-aliasing logic is used for this <see cref="FontSpec" />.
+ /// </summary>
+ public static bool IsAntiAlias = false;
+ /// <summary>
+ /// Default value for <see cref="FontSpec.DropShadowColor"/>, which determines
+ /// the color of the drop shadow for this <see cref="FontSpec" />.
+ /// </summary>
+ public static Color DropShadowColor = Color.Black;
+ /// <summary>
+ /// Default value for <see cref="FontSpec.DropShadowAngle"/>, which determines
+ /// the offset angle of the drop shadow for this <see cref="FontSpec" />.
+ /// </summary>
+ public static float DropShadowAngle = 45f;
+ /// <summary>
+ /// Default value for <see cref="FontSpec.DropShadowOffset"/>, which determines
+ /// the offset distance of the drop shadow for this <see cref="FontSpec" />.
+ /// </summary>
+ public static float DropShadowOffset = 0.05f;
+
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// The color of the font characters for this <see cref="FontSpec"/>.
+ /// Note that the border and background
+ /// colors are set using the <see cref="ZedGraph.LineBase.Color"/> and
+ /// <see cref="ZedGraph.Fill.Color"/> properties, respectively.
+ /// </summary>
+ /// <value>A system <see cref="System.Drawing.Color"/> reference.</value>
+ public Color FontColor
+ {
+ get { return _fontColor; }
+ set { _fontColor = value; }
+ }
+ /// <summary>
+ /// The font family name for this <see cref="FontSpec"/>.
+ /// </summary>
+ /// <value>A text string with the font family name, e.g., "Arial"</value>
+ public string Family
+ {
+ get { return _family; }
+ set
+ {
+ if ( value != _family )
+ {
+ _family = value;
+ Remake( _scaledSize / _size, this.Size, ref _scaledSize, ref _font );
+ }
+ }
+ }
+ /// <summary>
+ /// Determines whether this <see cref="FontSpec"/> is
+ /// drawn with bold typeface.
+ /// </summary>
+ /// <value>A boolean value, true for bold, false for normal</value>
+ public bool IsBold
+ {
+ get { return _isBold; }
+ set
+ {
+ if ( value != _isBold )
+ {
+ _isBold = value;
+ Remake( _scaledSize / _size, this.Size, ref _scaledSize, ref _font );
+ }
+ }
+ }
+ /// <summary>
+ /// Determines whether this <see cref="FontSpec"/> is
+ /// drawn with italic typeface.
+ /// </summary>
+ /// <value>A boolean value, true for italic, false for normal</value>
+ public bool IsItalic
+ {
+ get { return _isItalic; }
+ set
+ {
+ if ( value != _isItalic )
+ {
+ _isItalic = value;
+ Remake( _scaledSize / _size, this.Size, ref _scaledSize, ref _font );
+ }
+ }
+ }
+ /// <summary>
+ /// Determines whether this <see cref="FontSpec"/> is
+ /// drawn with underlined typeface.
+ /// </summary>
+ /// <value>A boolean value, true for underline, false for normal</value>
+ public bool IsUnderline
+ {
+ get { return _isUnderline; }
+ set
+ {
+ if ( value != _isUnderline )
+ {
+ _isUnderline = value;
+ Remake( _scaledSize / _size, this.Size, ref _scaledSize, ref _font );
+ }
+ }
+ }
+ /// <summary>
+ /// The angle at which this <see cref="FontSpec"/> object is drawn.
+ /// </summary>
+ /// <value>The angle of the font, measured in anti-clockwise degrees from
+ /// horizontal. Negative values are permitted.</value>
+ public float Angle
+ {
+ get { return _angle; }
+ set { _angle = value; }
+ }
+
+ /// <summary>
+ /// Determines the alignment with which this
+ /// <see cref="FontSpec"/> object is drawn. This alignment really only
+ /// affects multi-line strings.
+ /// </summary>
+ /// <value>A <see cref="StringAlignment"/> enumeration.</value>
+ public StringAlignment StringAlignment
+ {
+ get { return _stringAlignment; }
+ set { _stringAlignment = value; }
+ }
+
+ /// <summary>
+ /// The size of the font for this <see cref="FontSpec"/> object.
+ /// </summary>
+ /// <value>The size of the font, measured in points (1/72 inch).</value>
+ public float Size
+ {
+ get { return _size; }
+ set
+ {
+ if ( value != _size )
+ {
+ Remake( _scaledSize / _size * value, _size, ref _scaledSize,
+ ref _font );
+ _size = value;
+ }
+ }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="Border"/> class used to draw the border border
+ /// around this text.
+ /// </summary>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="FontSpec"/>, which controls how the background
+ /// behind the text is filled.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the <see cref="FontSpec" /> will be
+ /// drawn using anti-aliasing logic within GDI+.
+ /// </summary>
+ /// <remarks>
+ /// If this property is set to true, it will override the current setting of
+ /// <see cref="Graphics.SmoothingMode" /> by setting the value temporarily to
+ /// <see cref="SmoothingMode.HighQuality" />. If this property is set to false,
+ /// the the current setting of <see cref="Graphics.SmoothingMode" /> will be
+ /// left as-is.
+ /// </remarks>
+ public bool IsAntiAlias
+ {
+ get { return _isAntiAlias; }
+ set { _isAntiAlias = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines if the <see cref="FontSpec" /> will be
+ /// displayed with a drop shadow.
+ /// </summary>
+ /// <seealso cref="DropShadowColor" />
+ /// <seealso cref="DropShadowAngle" />
+ /// <seealso cref="DropShadowOffset" />
+ public bool IsDropShadow
+ {
+ get { return _isDropShadow; }
+ set { _isDropShadow = value; }
+ }
+ /// <summary>
+ /// Gets or sets the color of the drop shadow for this <see cref="FontSpec" />.
+ /// </summary>
+ /// <remarks>
+ /// This value only applies if <see cref="IsDropShadow" /> is true.
+ /// </remarks>
+ /// <seealso cref="IsDropShadow" />
+ /// <seealso cref="DropShadowAngle" />
+ /// <seealso cref="DropShadowOffset" />
+ public Color DropShadowColor
+ {
+ get { return _dropShadowColor; }
+ set { _dropShadowColor = value; }
+ }
+ /// <summary>
+ /// Gets or sets the offset angle of the drop shadow for this <see cref="FontSpec" />.
+ /// </summary>
+ /// <remarks>
+ /// This value only applies if <see cref="IsDropShadow" /> is true.
+ /// </remarks>
+ /// <value>The angle, measured in anti-clockwise degrees from
+ /// horizontal. Negative values are permitted.</value>
+ /// <seealso cref="IsDropShadow" />
+ /// <seealso cref="DropShadowColor" />
+ /// <seealso cref="DropShadowOffset" />
+ public float DropShadowAngle
+ {
+ get { return _dropShadowAngle; }
+ set { _dropShadowAngle = value; }
+ }
+ /// <summary>
+ /// Gets or sets the offset distance of the drop shadow for this <see cref="FontSpec" />.
+ /// </summary>
+ /// <remarks>
+ /// This value only applies if <see cref="IsDropShadow" /> is true.
+ /// </remarks>
+ /// <value>The offset distance, measured as a fraction of the scaled font height.</value>
+ /// <seealso cref="IsDropShadow" />
+ /// <seealso cref="DropShadowColor" />
+ /// <seealso cref="DropShadowAngle" />
+ public float DropShadowOffset
+ {
+ get { return _dropShadowOffset; }
+ set { _dropShadowOffset = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Construct a <see cref="FontSpec"/> object with default properties.
+ /// </summary>
+ public FontSpec()
+ : this( "Arial", 12, Color.Black, false, false, false )
+ {
+ }
+
+ /// <summary>
+ /// Construct a <see cref="FontSpec"/> object with the given properties. All other properties
+ /// are defaulted according to the values specified in the <see cref="Default"/>
+ /// default class.
+ /// </summary>
+ /// <param name="family">A text string representing the font family
+ /// (default is "Arial")</param>
+ /// <param name="size">A size of the font in points. This size will be scaled
+ /// based on the ratio of the <see cref="PaneBase.Rect"/> dimension to the
+ /// <see cref="PaneBase.BaseDimension"/> of the <see cref="GraphPane"/> object. </param>
+ /// <param name="color">The color with which to render the font</param>
+ /// <param name="isBold">true for a bold typeface, false otherwise</param>
+ /// <param name="isItalic">true for an italic typeface, false otherwise</param>
+ /// <param name="isUnderline">true for an underlined font, false otherwise</param>
+ public FontSpec( string family, float size, Color color, bool isBold,
+ bool isItalic, bool isUnderline )
+ {
+ Init( family, size, color, isBold, isItalic, isUnderline,
+ Default.FillColor, Default.FillBrush, Default.FillType );
+ }
+
+ /// <summary>
+ /// Construct a <see cref="FontSpec"/> object with the given properties. All other properties
+ /// are defaulted according to the values specified in the <see cref="Default"/>
+ /// default class.
+ /// </summary>
+ /// <param name="family">A text string representing the font family
+ /// (default is "Arial")</param>
+ /// <param name="size">A size of the font in points. This size will be scaled
+ /// based on the ratio of the <see cref="PaneBase.Rect"/> dimension to the
+ /// <see cref="PaneBase.BaseDimension"/> of the <see cref="GraphPane"/> object. </param>
+ /// <param name="color">The color with which to render the font</param>
+ /// <param name="isBold">true for a bold typeface, false otherwise</param>
+ /// <param name="isItalic">true for an italic typeface, false otherwise</param>
+ /// <param name="isUnderline">true for an underlined font, false otherwise</param>
+ /// <param name="fillColor">The <see cref="Color"/> to use for filling in the text background</param>
+ /// <param name="fillBrush">The <see cref="Brush"/> to use for filling in the text background</param>
+ /// <param name="fillType">The <see cref="ZedGraph.FillType"/> to use for the
+ /// text background</param>
+ public FontSpec( string family, float size, Color color, bool isBold,
+ bool isItalic, bool isUnderline, Color fillColor, Brush fillBrush,
+ FillType fillType )
+ {
+ Init( family, size, color, isBold, isItalic, isUnderline,
+ fillColor, fillBrush, fillType );
+ }
+
+ private void Init( string family, float size, Color color, bool isBold,
+ bool isItalic, bool isUnderline, Color fillColor, Brush fillBrush,
+ FillType fillType )
+ {
+ _fontColor = color;
+ _family = family;
+ _isBold = isBold;
+ _isItalic = isItalic;
+ _isUnderline = isUnderline;
+ _size = size;
+ _angle = 0F;
+
+ _isAntiAlias = Default.IsAntiAlias;
+ _stringAlignment = Default.StringAlignment;
+ _isDropShadow = Default.IsDropShadow;
+ _dropShadowColor = Default.DropShadowColor;
+ _dropShadowAngle = Default.DropShadowAngle;
+ _dropShadowOffset = Default.DropShadowOffset;
+
+ _fill = new Fill( fillColor, fillBrush, fillType );
+ _border = new Border( true, Color.Black, 1.0F );
+
+ _scaledSize = -1;
+ Remake( 1.0F, _size, ref _scaledSize, ref _font );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The FontSpec object from which to copy</param>
+ public FontSpec( FontSpec rhs )
+ {
+ _fontColor = rhs.FontColor;
+ _family = rhs.Family;
+ _isBold = rhs.IsBold;
+ _isItalic = rhs.IsItalic;
+ _isUnderline = rhs.IsUnderline;
+ _fill = rhs.Fill.Clone();
+ _border = rhs.Border.Clone();
+ _isAntiAlias = rhs._isAntiAlias;
+
+ _stringAlignment = rhs.StringAlignment;
+ _angle = rhs.Angle;
+ _size = rhs.Size;
+
+ _isDropShadow = rhs._isDropShadow;
+ _dropShadowColor = rhs._dropShadowColor;
+ _dropShadowAngle = rhs._dropShadowAngle;
+ _dropShadowOffset = rhs._dropShadowOffset;
+
+ _scaledSize = rhs._scaledSize;
+ Remake( 1.0F, _size, ref _scaledSize, ref _font );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public FontSpec Clone()
+ {
+ return new FontSpec( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ // Change to 2 with addition of isDropShadow, dropShadowColor, dropShadowAngle, dropShadowOffset
+ // changed to 10 with the version 5 refactor -- not backwards compatible
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected FontSpec( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _fontColor = (Color)info.GetValue( "fontColor", typeof( Color ) );
+ _family = info.GetString( "family" );
+ _isBold = info.GetBoolean( "isBold" );
+ _isItalic = info.GetBoolean( "isItalic" );
+ _isUnderline = info.GetBoolean( "isUnderline" );
+ _isAntiAlias = info.GetBoolean( "isAntiAlias" );
+
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+ _border = (Border)info.GetValue( "border", typeof( Border ) );
+ _angle = info.GetSingle( "angle" );
+ _stringAlignment = (StringAlignment)info.GetValue( "stringAlignment", typeof( StringAlignment ) );
+ _size = info.GetSingle( "size" );
+
+ _isDropShadow = info.GetBoolean( "isDropShadow" );
+ _dropShadowColor = (Color)info.GetValue( "dropShadowColor", typeof( Color ) );
+ _dropShadowAngle = info.GetSingle( "dropShadowAngle" );
+ _dropShadowOffset = info.GetSingle( "dropShadowOffset" );
+
+ _scaledSize = -1;
+ Remake( 1.0F, _size, ref _scaledSize, ref _font );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "fontColor", _fontColor );
+ info.AddValue( "family", _family );
+ info.AddValue( "isBold", _isBold );
+ info.AddValue( "isItalic", _isItalic );
+ info.AddValue( "isUnderline", _isUnderline );
+ info.AddValue( "isAntiAlias", _isAntiAlias );
+
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "angle", _angle );
+ info.AddValue( "stringAlignment", _stringAlignment );
+ info.AddValue( "size", _size );
+
+ info.AddValue( "isDropShadow", _isDropShadow );
+ info.AddValue( "dropShadowColor", _dropShadowColor );
+ info.AddValue( "dropShadowAngle", _dropShadowAngle );
+ info.AddValue( "dropShadowOffset", _dropShadowOffset );
+ }
+ #endregion
+
+ #region Font Construction Methods
+ /// <summary>
+ /// Recreate the font based on a new scaled size. The font
+ /// will only be recreated if the scaled size has changed by
+ /// at least 0.1 points.
+ /// </summary>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="size">The unscaled size of the font, in points</param>
+ /// <param name="scaledSize">The scaled size of the font, in points</param>
+ /// <param name="font">A reference to the <see cref="Font"/> object</param>
+ private void Remake( float scaleFactor, float size, ref float scaledSize, ref Font font )
+ {
+ float newSize = size * scaleFactor;
+
+ float oldSize = ( font == null ) ? 0.0f : font.Size;
+
+ // Regenerate the font only if the size has changed significantly
+ if ( font == null ||
+ Math.Abs( newSize - oldSize ) > 0.1 ||
+ font.Name != this.Family ||
+ font.Bold != _isBold ||
+ font.Italic != _isItalic ||
+ font.Underline != _isUnderline )
+ {
+ FontStyle style = FontStyle.Regular;
+ style = ( _isBold ? FontStyle.Bold : style ) |
+ ( _isItalic ? FontStyle.Italic : style ) |
+ ( _isUnderline ? FontStyle.Underline : style );
+
+ scaledSize = size * (float)scaleFactor;
+ font = new Font( _family, scaledSize, style, GraphicsUnit.World );
+ }
+ }
+
+ /// <summary>
+ /// Get the <see cref="Font"/> class for the current scaled font.
+ /// </summary>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>Returns a reference to a <see cref="Font"/> object
+ /// with a size of <see cref="_scaledSize"/>, and font <see cref="Family"/>.
+ /// </returns>
+ public Font GetFont( float scaleFactor )
+ {
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ return _font;
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render the specified <paramref name="text"/> to the specifed
+ /// <see cref="Graphics"/> device. The text, border, and fill options
+ /// will be rendered as required.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="text">A string value containing the text to be
+ /// displayed. This can be multiple lines, separated by newline ('\n')
+ /// characters</param>
+ /// <param name="x">The X location to display the text, in screen
+ /// coordinates, relative to the horizontal (<see cref="AlignH"/>)
+ /// alignment parameter <paramref name="alignH"/></param>
+ /// <param name="y">The Y location to display the text, in screen
+ /// coordinates, relative to the vertical (<see cref="AlignV"/>
+ /// alignment parameter <paramref name="alignV"/></param>
+ /// <param name="alignH">A horizontal alignment parameter specified
+ /// using the <see cref="AlignH"/> enum type</param>
+ /// <param name="alignV">A vertical alignment parameter specified
+ /// using the <see cref="AlignV"/> enum type</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void Draw( Graphics g, PaneBase pane, string text, float x,
+ float y, AlignH alignH, AlignV alignV,
+ float scaleFactor )
+ {
+ this.Draw( g, pane, text, x, y, alignH, alignV,
+ scaleFactor, new SizeF() );
+ }
+
+ /// <summary>
+ /// Render the specified <paramref name="text"/> to the specifed
+ /// <see cref="Graphics"/> device. The text, border, and fill options
+ /// will be rendered as required.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="text">A string value containing the text to be
+ /// displayed. This can be multiple lines, separated by newline ('\n')
+ /// characters</param>
+ /// <param name="x">The X location to display the text, in screen
+ /// coordinates, relative to the horizontal (<see cref="AlignH"/>)
+ /// alignment parameter <paramref name="alignH"/></param>
+ /// <param name="y">The Y location to display the text, in screen
+ /// coordinates, relative to the vertical (<see cref="AlignV"/>
+ /// alignment parameter <paramref name="alignV"/></param>
+ /// <param name="alignH">A horizontal alignment parameter specified
+ /// using the <see cref="AlignH"/> enum type</param>
+ /// <param name="alignV">A vertical alignment parameter specified
+ /// using the <see cref="AlignV"/> enum type</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="layoutArea">The limiting area (<see cref="SizeF"/>) into which the text
+ /// must fit. The actual rectangle may be smaller than this, but the text will be wrapped
+ /// to accomodate the area.</param>
+ public void Draw( Graphics g, PaneBase pane, string text, float x,
+ float y, AlignH alignH, AlignV alignV,
+ float scaleFactor, SizeF layoutArea )
+ {
+ // make sure the font size is properly scaled
+ //Remake( scaleFactor, this.Size, ref this.scaledSize, ref this.font );
+
+ SmoothingMode sModeSave = g.SmoothingMode;
+ TextRenderingHint sHintSave = g.TextRenderingHint;
+ if ( _isAntiAlias )
+ {
+ g.SmoothingMode = SmoothingMode.HighQuality;
+ g.TextRenderingHint = TextRenderingHint.AntiAlias;
+ }
+
+ SizeF sizeF;
+ if ( layoutArea.IsEmpty )
+ sizeF = MeasureString( g, text, scaleFactor );
+ else
+ sizeF = MeasureString( g, text, scaleFactor, layoutArea );
+
+ // Save the old transform matrix for later restoration
+ Matrix saveMatrix = g.Transform;
+ g.Transform = SetupMatrix( g.Transform, x, y, sizeF, alignH, alignV, _angle );
+
+ // Create a rectangle representing the border around the
+ // text. Note that, while the text is drawn based on the
+ // TopCenter position, the rectangle is drawn based on
+ // the TopLeft position. Therefore, move the rectangle
+ // width/2 to the left to align it properly
+ RectangleF rectF = new RectangleF( -sizeF.Width / 2.0F, 0.0F,
+ sizeF.Width, sizeF.Height );
+
+ // If the background is to be filled, fill it
+ _fill.Draw( g, rectF );
+
+ // Draw the border around the text if required
+ _border.Draw( g, pane, scaleFactor, rectF );
+
+ // make a center justified StringFormat alignment
+ // for drawing the text
+ StringFormat strFormat = new StringFormat();
+ strFormat.Alignment = _stringAlignment;
+ // if ( this.stringAlignment == StringAlignment.Far )
+ // g.TranslateTransform( sizeF.Width / 2.0F, 0F, MatrixOrder.Prepend );
+ // else if ( this.stringAlignment == StringAlignment.Near )
+ // g.TranslateTransform( -sizeF.Width / 2.0F, 0F, MatrixOrder.Prepend );
+
+
+ // Draw the drop shadow text. Note that the coordinate system
+ // is set up such that 0,0 is at the location where the
+ // CenterTop of the text needs to be.
+ if ( _isDropShadow )
+ {
+ float xShift = (float)( Math.Cos( _dropShadowAngle ) *
+ _dropShadowOffset * _font.Height );
+ float yShift = (float)( Math.Sin( _dropShadowAngle ) *
+ _dropShadowOffset * _font.Height );
+ RectangleF rectD = rectF;
+ rectD.Offset( xShift, yShift );
+ // make a solid brush for rendering the font itself
+ using ( SolidBrush brushD = new SolidBrush( _dropShadowColor ) )
+ g.DrawString( text, _font, brushD, rectD, strFormat );
+ }
+
+ // make a solid brush for rendering the font itself
+ using ( SolidBrush brush = new SolidBrush( _fontColor ) )
+ {
+ // Draw the actual text. Note that the coordinate system
+ // is set up such that 0,0 is at the location where the
+ // CenterTop of the text needs to be.
+ //RectangleF layoutArea = new RectangleF( 0.0F, 0.0F, sizeF.Width, sizeF.Height );
+ g.DrawString( text, _font, brush, rectF, strFormat );
+ }
+
+ // Restore the transform matrix back to original
+ g.Transform = saveMatrix;
+
+ g.SmoothingMode = sModeSave;
+ g.TextRenderingHint = sHintSave;
+ }
+
+ /// <summary>
+ /// Render the specified <paramref name="text"/> to the specifed
+ /// <see cref="Graphics"/> device. The text, border, and fill options
+ /// will be rendered as required. This special case method will show the
+ /// specified text as a power of 10, using the <see cref="Default.SuperSize"/>
+ /// and <see cref="Default.SuperShift"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="text">A string value containing the text to be
+ /// displayed. This can be multiple lines, separated by newline ('\n')
+ /// characters</param>
+ /// <param name="x">The X location to display the text, in screen
+ /// coordinates, relative to the horizontal (<see cref="AlignH"/>)
+ /// alignment parameter <paramref name="alignH"/></param>
+ /// <param name="y">The Y location to display the text, in screen
+ /// coordinates, relative to the vertical (<see cref="AlignV"/>
+ /// alignment parameter <paramref name="alignV"/></param>
+ /// <param name="alignH">A horizontal alignment parameter specified
+ /// using the <see cref="AlignH"/> enum type</param>
+ /// <param name="alignV">A vertical alignment parameter specified
+ /// using the <see cref="AlignV"/> enum type</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DrawTenPower( Graphics g, GraphPane pane, string text, float x,
+ float y, AlignH alignH, AlignV alignV,
+ float scaleFactor )
+ {
+ SmoothingMode sModeSave = g.SmoothingMode;
+ TextRenderingHint sHintSave = g.TextRenderingHint;
+ if ( _isAntiAlias )
+ {
+ g.SmoothingMode = SmoothingMode.HighQuality;
+ g.TextRenderingHint = TextRenderingHint.AntiAlias;
+ }
+
+ // make sure the font size is properly scaled
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ float scaledSuperSize = _scaledSize * Default.SuperSize;
+ Remake( scaleFactor, this.Size * Default.SuperSize, ref scaledSuperSize,
+ ref _superScriptFont );
+
+ // Get the width and height of the text
+ SizeF size10 = g.MeasureString( "10", _font );
+ SizeF sizeText = g.MeasureString( text, _superScriptFont );
+ SizeF totSize = new SizeF( size10.Width + sizeText.Width,
+ size10.Height + sizeText.Height * Default.SuperShift );
+ float charWidth = g.MeasureString( "x", _superScriptFont ).Width;
+
+ // Save the old transform matrix for later restoration
+ Matrix saveMatrix = g.Transform;
+
+ g.Transform = SetupMatrix( g.Transform, x, y, totSize, alignH, alignV, _angle );
+
+ // make a center justified StringFormat alignment
+ // for drawing the text
+ StringFormat strFormat = new StringFormat();
+ strFormat.Alignment = _stringAlignment;
+
+ // Create a rectangle representing the border around the
+ // text. Note that, while the text is drawn based on the
+ // TopCenter position, the rectangle is drawn based on
+ // the TopLeft position. Therefore, move the rectangle
+ // width/2 to the left to align it properly
+ RectangleF rectF = new RectangleF( -totSize.Width / 2.0F, 0.0F,
+ totSize.Width, totSize.Height );
+
+ // If the background is to be filled, fill it
+ _fill.Draw( g, rectF );
+
+ // Draw the border around the text if required
+ _border.Draw( g, pane, scaleFactor, rectF );
+
+ // make a solid brush for rendering the font itself
+ using ( SolidBrush brush = new SolidBrush( _fontColor ) )
+ {
+ // Draw the actual text. Note that the coordinate system
+ // is set up such that 0,0 is at the location where the
+ // CenterTop of the text needs to be.
+ g.DrawString( "10", _font, brush,
+ ( -totSize.Width + size10.Width ) / 2.0F,
+ sizeText.Height * Default.SuperShift, strFormat );
+ g.DrawString( text, _superScriptFont, brush,
+ ( totSize.Width - sizeText.Width - charWidth ) / 2.0F,
+ 0.0F,
+ strFormat );
+ }
+
+ // Restore the transform matrix back to original
+ g.Transform = saveMatrix;
+
+ g.SmoothingMode = sModeSave;
+ g.TextRenderingHint = sHintSave;
+ }
+ #endregion
+
+ #region Sizing Methods
+ /// <summary>
+ /// Get the height of the scaled font
+ /// </summary>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled font height, in pixels</returns>
+ public float GetHeight( float scaleFactor )
+ {
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ float height = _font.Height;
+ if ( _isDropShadow )
+ height += (float)( Math.Sin( _dropShadowAngle ) * _dropShadowOffset * _font.Height );
+ return height;
+ }
+ /// <summary>
+ /// Get the average character width of the scaled font. The average width is
+ /// based on the character 'x'
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled font width, in pixels</returns>
+ public float GetWidth( Graphics g, float scaleFactor )
+ {
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ return g.MeasureString( "x", _font ).Width;
+ }
+
+ /// <summary>
+ /// Get the total width of the specified text string
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">The text string for which the width is to be calculated
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled text width, in pixels</returns>
+ public float GetWidth( Graphics g, string text, float scaleFactor )
+ {
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ float width = g.MeasureString( text, _font ).Width;
+ if ( _isDropShadow )
+ width += (float)( Math.Cos( _dropShadowAngle ) * _dropShadowOffset * _font.Height );
+ return width;
+ }
+ /// <summary>
+ /// Get a <see cref="SizeF"/> struct representing the width and height
+ /// of the specified text string, based on the scaled font size
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">The text string for which the width is to be calculated
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled text dimensions, in pixels, in the form of
+ /// a <see cref="SizeF"/> struct</returns>
+ public SizeF MeasureString( Graphics g, string text, float scaleFactor )
+ {
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ SizeF size = g.MeasureString( text, _font );
+ if ( _isDropShadow )
+ {
+ size.Width += (float)( Math.Cos( _dropShadowAngle ) *
+ _dropShadowOffset * _font.Height );
+ size.Height += (float)( Math.Sin( _dropShadowAngle ) *
+ _dropShadowOffset * _font.Height );
+ }
+ return size;
+ }
+
+ /// <summary>
+ /// Get a <see cref="SizeF"/> struct representing the width and height
+ /// of the specified text string, based on the scaled font size, and using
+ /// the specified <see cref="SizeF"/> as an outer limit.
+ /// </summary>
+ /// <remarks>
+ /// This method will allow the text to wrap as necessary to fit the
+ /// <see paramref="layoutArea"/>.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">The text string for which the width is to be calculated
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="layoutArea">The limiting area (<see cref="SizeF"/>) into which the text
+ /// must fit. The actual rectangle may be smaller than this, but the text will be wrapped
+ /// to accomodate the area.</param>
+ /// <returns>The scaled text dimensions, in pixels, in the form of
+ /// a <see cref="SizeF"/> struct</returns>
+ public SizeF MeasureString( Graphics g, string text, float scaleFactor, SizeF layoutArea )
+ {
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+ SizeF size = g.MeasureString( text, _font, layoutArea );
+ if ( _isDropShadow )
+ {
+ size.Width += (float)( Math.Cos( _dropShadowAngle ) *
+ _dropShadowOffset * _font.Height );
+ size.Height += (float)( Math.Sin( _dropShadowAngle ) *
+ _dropShadowOffset * _font.Height );
+ }
+ return size;
+ }
+
+ /// <summary>
+ /// Get a <see cref="SizeF"/> struct representing the width and height
+ /// of the bounding box for the specified text string, based on the scaled font size.
+ /// </summary>
+ /// <remarks>
+ /// This routine differs from <see cref="MeasureString(Graphics,string,float)"/> in that it takes into
+ /// account the rotation angle of the font, and gives the dimensions of the
+ /// bounding box that encloses the text at the specified angle.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">The text string for which the width is to be calculated
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled text dimensions, in pixels, in the form of
+ /// a <see cref="SizeF"/> struct</returns>
+ public SizeF BoundingBox( Graphics g, string text, float scaleFactor )
+ {
+ return BoundingBox( g, text, scaleFactor, new SizeF() );
+ }
+
+ /// <summary>
+ /// Get a <see cref="SizeF"/> struct representing the width and height
+ /// of the bounding box for the specified text string, based on the scaled font size.
+ /// </summary>
+ /// <remarks>
+ /// This routine differs from <see cref="MeasureString(Graphics,string,float)"/> in that it takes into
+ /// account the rotation angle of the font, and gives the dimensions of the
+ /// bounding box that encloses the text at the specified angle.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">The text string for which the width is to be calculated
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="layoutArea">The limiting area (<see cref="SizeF"/>) into which the text
+ /// must fit. The actual rectangle may be smaller than this, but the text will be wrapped
+ /// to accomodate the area.</param>
+ /// <returns>The scaled text dimensions, in pixels, in the form of
+ /// a <see cref="SizeF"/> struct</returns>
+ public SizeF BoundingBox( Graphics g, string text, float scaleFactor, SizeF layoutArea )
+ {
+ //Remake( scaleFactor, this.Size, ref this.scaledSize, ref this.font );
+ SizeF s;
+ if ( layoutArea.IsEmpty )
+ s = MeasureString( g, text, scaleFactor );
+ else
+ s = MeasureString( g, text, scaleFactor, layoutArea );
+
+ float cs = (float)Math.Abs( Math.Cos( _angle * Math.PI / 180.0 ) );
+ float sn = (float)Math.Abs( Math.Sin( _angle * Math.PI / 180.0 ) );
+
+ SizeF s2 = new SizeF( s.Width * cs + s.Height * sn,
+ s.Width * sn + s.Height * cs );
+
+ return s2;
+ }
+
+ /// <summary>
+ /// Get a <see cref="SizeF"/> struct representing the width and height
+ /// of the bounding box for the specified text string, based on the scaled font size.
+ /// </summary>
+ /// <remarks>
+ /// This special case method will show the specified string as a power of 10,
+ /// superscripted and downsized according to the
+ /// <see cref="Default.SuperSize"/> and <see cref="Default.SuperShift"/>.
+ /// This routine differs from <see cref="MeasureString(Graphics,string,float)"/> in that it takes into
+ /// account the rotation angle of the font, and gives the dimensions of the
+ /// bounding box that encloses the text at the specified angle.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">The text string for which the width is to be calculated
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled text dimensions, in pixels, in the form of
+ /// a <see cref="SizeF"/> struct</returns>
+ public SizeF BoundingBoxTenPower( Graphics g, string text, float scaleFactor )
+ {
+ //Remake( scaleFactor, this.Size, ref this.scaledSize, ref this.font );
+ float scaledSuperSize = _scaledSize * Default.SuperSize;
+ Remake( scaleFactor, this.Size * Default.SuperSize, ref scaledSuperSize,
+ ref _superScriptFont );
+
+ // Get the width and height of the text
+ SizeF size10 = MeasureString( g, "10", scaleFactor );
+ SizeF sizeText = g.MeasureString( text, _superScriptFont );
+
+ if ( _isDropShadow )
+ {
+ sizeText.Width += (float)( Math.Cos( _dropShadowAngle ) *
+ _dropShadowOffset * _superScriptFont.Height );
+ sizeText.Height += (float)( Math.Sin( _dropShadowAngle ) *
+ _dropShadowOffset * _superScriptFont.Height );
+ }
+
+ SizeF totSize = new SizeF( size10.Width + sizeText.Width,
+ size10.Height + sizeText.Height * Default.SuperShift );
+
+
+ float cs = (float)Math.Abs( Math.Cos( _angle * Math.PI / 180.0 ) );
+ float sn = (float)Math.Abs( Math.Sin( _angle * Math.PI / 180.0 ) );
+
+ SizeF s2 = new SizeF( totSize.Width * cs + totSize.Height * sn,
+ totSize.Width * sn + totSize.Height * cs );
+
+ return s2;
+ }
+
+
+ /// <summary>
+ /// Determines if the specified screen point lies within the bounding box of
+ /// the text, taking into account alignment and rotation parameters.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixel units</param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">A string value containing the text to be
+ /// displayed. This can be multiple lines, separated by newline ('\n')
+ /// characters</param>
+ /// <param name="x">The X location to display the text, in screen
+ /// coordinates, relative to the horizontal (<see cref="AlignH"/>)
+ /// alignment parameter <paramref name="alignH"/></param>
+ /// <param name="y">The Y location to display the text, in screen
+ /// coordinates, relative to the vertical (<see cref="AlignV"/>
+ /// alignment parameter <paramref name="alignV"/></param>
+ /// <param name="alignH">A horizontal alignment parameter specified
+ /// using the <see cref="AlignH"/> enum type</param>
+ /// <param name="alignV">A vertical alignment parameter specified
+ /// using the <see cref="AlignV"/> enum type</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies within the bounding box, false otherwise</returns>
+ public bool PointInBox( PointF pt, Graphics g, string text, float x,
+ float y, AlignH alignH, AlignV alignV,
+ float scaleFactor )
+ {
+ return PointInBox( pt, g, text, x, y, alignH, alignV, scaleFactor, new SizeF() );
+ }
+
+ /// <summary>
+ /// Determines if the specified screen point lies within the bounding box of
+ /// the text, taking into account alignment and rotation parameters.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixel units</param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">A string value containing the text to be
+ /// displayed. This can be multiple lines, separated by newline ('\n')
+ /// characters</param>
+ /// <param name="x">The X location to display the text, in screen
+ /// coordinates, relative to the horizontal (<see cref="AlignH"/>)
+ /// alignment parameter <paramref name="alignH"/></param>
+ /// <param name="y">The Y location to display the text, in screen
+ /// coordinates, relative to the vertical (<see cref="AlignV"/>
+ /// alignment parameter <paramref name="alignV"/></param>
+ /// <param name="alignH">A horizontal alignment parameter specified
+ /// using the <see cref="AlignH"/> enum type</param>
+ /// <param name="alignV">A vertical alignment parameter specified
+ /// using the <see cref="AlignV"/> enum type</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="layoutArea">The limiting area (<see cref="SizeF"/>) into which the text
+ /// must fit. The actual rectangle may be smaller than this, but the text will be wrapped
+ /// to accomodate the area.</param>
+ /// <returns>true if the point lies within the bounding box, false otherwise</returns>
+ public bool PointInBox( PointF pt, Graphics g, string text, float x,
+ float y, AlignH alignH, AlignV alignV,
+ float scaleFactor, SizeF layoutArea )
+ {
+ // make sure the font size is properly scaled
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+
+ // Get the width and height of the text
+ SizeF sizeF;
+ if ( layoutArea.IsEmpty )
+ sizeF = g.MeasureString( text, _font );
+ else
+ sizeF = g.MeasureString( text, _font, layoutArea );
+
+ // Create a bounding box rectangle for the text
+ RectangleF rect = new RectangleF( new PointF( -sizeF.Width / 2.0F, 0.0F ), sizeF );
+
+ // Build a transform matrix that inverts that drawing transform
+ // in this manner, the point is brought back to the box, rather
+ // than vice-versa. This allows the container check to be a simple
+ // RectangleF.Contains, since the rectangle won't be rotated.
+ Matrix matrix = GetMatrix( x, y, sizeF, alignH, alignV, _angle );
+
+ PointF[] pts = new PointF[1];
+ pts[0] = pt;
+ matrix.TransformPoints( pts );
+
+ return rect.Contains( pts[0] );
+ }
+
+ private Matrix SetupMatrix( Matrix matrix, float x, float y, SizeF sizeF, AlignH alignH,
+ AlignV alignV, float angle )
+ {
+ // Move the coordinate system to local coordinates
+ // of this text object (that is, at the specified
+ // x,y location)
+ matrix.Translate( x, y, MatrixOrder.Prepend );
+
+ // Rotate the coordinate system according to the
+ // specified angle of the FontSpec
+ if ( _angle != 0.0F )
+ matrix.Rotate( -angle, MatrixOrder.Prepend );
+
+ // Since the text will be drawn by g.DrawString()
+ // assuming the location is the TopCenter
+ // (the Font is aligned using StringFormat to the
+ // center so multi-line text is center justified),
+ // shift the coordinate system so that we are
+ // actually aligned per the caller specified position
+ float xa, ya;
+ if ( alignH == AlignH.Left )
+ xa = sizeF.Width / 2.0F;
+ else if ( alignH == AlignH.Right )
+ xa = -sizeF.Width / 2.0F;
+ else
+ xa = 0.0F;
+
+ if ( alignV == AlignV.Center )
+ ya = -sizeF.Height / 2.0F;
+ else if ( alignV == AlignV.Bottom )
+ ya = -sizeF.Height;
+ else
+ ya = 0.0F;
+
+ // Shift the coordinates to accomodate the alignment
+ // parameters
+ matrix.Translate( xa, ya, MatrixOrder.Prepend );
+
+ return matrix;
+ }
+
+ private Matrix GetMatrix( float x, float y, SizeF sizeF, AlignH alignH, AlignV alignV,
+ float angle )
+ {
+ // Build a transform matrix that inverts that drawing transform
+ // in this manner, the point is brought back to the box, rather
+ // than vice-versa. This allows the container check to be a simple
+ // RectangleF.Contains, since the rectangle won't be rotated.
+ Matrix matrix = new Matrix();
+
+ // In this case, the bounding box is anchored to the
+ // top-left of the text box. Handle the alignment
+ // as needed.
+ float xa, ya;
+ if ( alignH == AlignH.Left )
+ xa = sizeF.Width / 2.0F;
+ else if ( alignH == AlignH.Right )
+ xa = -sizeF.Width / 2.0F;
+ else
+ xa = 0.0F;
+
+ if ( alignV == AlignV.Center )
+ ya = -sizeF.Height / 2.0F;
+ else if ( alignV == AlignV.Bottom )
+ ya = -sizeF.Height;
+ else
+ ya = 0.0F;
+
+ // Shift the coordinates to accomodate the alignment
+ // parameters
+ matrix.Translate( -xa, -ya, MatrixOrder.Prepend );
+
+ // Rotate the coordinate system according to the
+ // specified angle of the FontSpec
+ if ( angle != 0.0F )
+ matrix.Rotate( angle, MatrixOrder.Prepend );
+
+ // Move the coordinate system to local coordinates
+ // of this text object (that is, at the specified
+ // x,y location)
+ matrix.Translate( -x, -y, MatrixOrder.Prepend );
+
+ return matrix;
+ }
+
+ /// <summary>
+ /// Returns a polygon that defines the bounding box of
+ /// the text, taking into account alignment and rotation parameters.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="text">A string value containing the text to be
+ /// displayed. This can be multiple lines, separated by newline ('\n')
+ /// characters</param>
+ /// <param name="x">The X location to display the text, in screen
+ /// coordinates, relative to the horizontal (<see cref="AlignH"/>)
+ /// alignment parameter <paramref name="alignH"/></param>
+ /// <param name="y">The Y location to display the text, in screen
+ /// coordinates, relative to the vertical (<see cref="AlignV"/>
+ /// alignment parameter <paramref name="alignV"/></param>
+ /// <param name="alignH">A horizontal alignment parameter specified
+ /// using the <see cref="AlignH"/> enum type</param>
+ /// <param name="alignV">A vertical alignment parameter specified
+ /// using the <see cref="AlignV"/> enum type</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="layoutArea">The limiting area (<see cref="SizeF"/>) into which the text
+ /// must fit. The actual rectangle may be smaller than this, but the text will be wrapped
+ /// to accomodate the area.</param>
+ /// <returns>A polygon of 4 points defining the area of this text</returns>
+ public PointF[] GetBox( Graphics g, string text, float x,
+ float y, AlignH alignH, AlignV alignV,
+ float scaleFactor, SizeF layoutArea )
+ {
+ // make sure the font size is properly scaled
+ Remake( scaleFactor, this.Size, ref _scaledSize, ref _font );
+
+ // Get the width and height of the text
+ SizeF sizeF;
+ if ( layoutArea.IsEmpty )
+ sizeF = g.MeasureString( text, _font );
+ else
+ sizeF = g.MeasureString( text, _font, layoutArea );
+
+ // Create a bounding box rectangle for the text
+ RectangleF rect = new RectangleF( new PointF( -sizeF.Width / 2.0F, 0.0F ), sizeF );
+
+ Matrix matrix = new Matrix();
+ SetupMatrix( matrix, x, y, sizeF, alignH, alignV, _angle );
+
+ PointF[] pts = new PointF[4];
+ pts[0] = new PointF( rect.Left, rect.Top );
+ pts[1] = new PointF( rect.Right, rect.Top );
+ pts[2] = new PointF( rect.Right, rect.Bottom );
+ pts[3] = new PointF( rect.Left, rect.Bottom );
+ matrix.TransformPoints( pts );
+
+ return pts;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/GapLabel.cs b/ZedGraph/GapLabel.cs
new file mode 100644
index 0000000..59a876a
--- /dev/null
+++ b/ZedGraph/GapLabel.cs
@@ -0,0 +1,175 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles the data associated with a text title and its associated font
+ /// properties. Inherits from <see cref="Label" />, and adds the <see cref="Gap" />
+ /// property for use by the <see cref="Axis" /> and <see cref="PaneBase" /> objects.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class GapLabel : Label, ICloneable, ISerializable
+ {
+ internal float _gap;
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to build a <see cref="GapLabel" /> from the text and the
+ /// associated font properties.
+ /// </summary>
+ /// <param name="text">The <see cref="string" /> representing the text to be
+ /// displayed</param>
+ /// <param name="fontFamily">The <see cref="String" /> font family name</param>
+ /// <param name="fontSize">The size of the font in points and scaled according
+ /// to the <see cref="PaneBase.CalcScaleFactor" /> logic.</param>
+ /// <param name="color">The <see cref="Color" /> instance representing the color
+ /// of the font</param>
+ /// <param name="isBold">true for a bold font face</param>
+ /// <param name="isItalic">true for an italic font face</param>
+ /// <param name="isUnderline">true for an underline font face</param>
+ public GapLabel( string text, string fontFamily, float fontSize, Color color, bool isBold,
+ bool isItalic, bool isUnderline )
+ : base( text, fontFamily, fontSize, color, isBold, isItalic, isUnderline )
+ {
+ _gap = Default.Gap;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">the <see cref="AxisLabel" /> instance to be copied.</param>
+ public GapLabel( GapLabel rhs )
+ : base( rhs )
+ {
+ _gap = rhs._gap;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new GapLabel Clone()
+ {
+ return new GapLabel( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the gap factor between this label and the opposing <see cref="Axis" />
+ /// or <see cref="Chart" />.
+ /// </summary>
+ /// <remarks>
+ /// This value is expressed as a fraction of the character height for the <see cref="GapLabel" />.
+ /// </remarks>
+ public float Gap
+ {
+ get { return _gap; }
+ set { _gap = value; }
+ }
+
+ /// <summary>
+ /// Calculate the size of the <see cref="Gap" /> based on the <see cref="Label.FontSpec" />
+ /// height, in pixel units and scaled according to <see paramref="scalefactor" />.
+ /// </summary>
+ /// <param name="scaleFactor">The scaling factor to be applied</param>
+ public float GetScaledGap( float scaleFactor )
+ {
+ return _fontSpec.GetHeight( scaleFactor ) * _gap;
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected GapLabel( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch2 = info.GetInt32( "schema2" );
+
+ _gap = info.GetSingle( "gap" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "gap", _gap );
+ }
+ #endregion
+
+ #region Default
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="GapLabel"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default <see cref="GapLabel.Gap" /> setting.
+ /// </summary>
+ public static float Gap = 0.3f;
+ }
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/GasGaugeNeedle.cs b/ZedGraph/GasGaugeNeedle.cs
new file mode 100644
index 0000000..d5b5d44
--- /dev/null
+++ b/ZedGraph/GasGaugeNeedle.cs
@@ -0,0 +1,593 @@
+//============================================================================
+//GasGaugeNeedle Class
+//Copyright � 2006 Jay Mistry
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System.Runtime.Serialization;
+using System.Drawing.Drawing2D;
+using System;
+using System.Text;
+using System.Drawing;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class representing a needle on the GasGuage chart
+ /// <see cref="GasGaugeNeedle"/>s.
+ /// </summary>
+ /// <author> Jay Mistry </author>
+ /// <version> $Revision: 1.2 $ $Date: 2007-08-11 14:37:47 $ </version>
+ [Serializable]
+ public class GasGaugeNeedle : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Value of this needle
+ /// </summary>
+ private double _needleValue;
+
+ /// <summary>
+ /// Width of the line being drawn
+ /// </summary>
+ private float _needleWidth;
+
+ /// <summary>
+ /// Color of the needle line
+ /// </summary>
+ private Color _color;
+
+ /// <summary>
+ /// Internally calculated angle that places this needle relative to the MinValue and
+ /// MaxValue of 180 degree GasGuage
+ /// </summary>
+ private float _sweepAngle;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="GasGaugeNeedle"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+
+ /// <summary>
+ /// A <see cref="ZedGraph.TextObj"/> which will customize the label display of this
+ /// <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ private TextObj _labelDetail;
+
+ /// <summary>
+ /// Private field that stores the <see cref="Border"/> class that defines the
+ /// properties of the border around this <see cref="GasGaugeNeedle"/>. Use the public
+ /// property <see cref="Border"/> to access this value.
+ /// </summary>
+ private Border _border;
+
+ /// <summary>
+ /// The bounding rectangle for this <see cref="GasGaugeNeedle"/>.
+ /// </summary>
+ private RectangleF _boundingRectangle;
+
+ /// <summary>
+ /// Private field to hold the GraphicsPath of this <see cref="GasGaugeNeedle"/> to be
+ /// used for 'hit testing'.
+ /// </summary>
+ private GraphicsPath _slicePath;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Create a new <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ /// <param name="label">The value associated with this <see cref="GasGaugeNeedle"/>
+ /// instance.</param>
+ /// <param name="color">The display color for this <see cref="GasGaugeNeedle"/>
+ /// instance.</param>
+ /// <param name="val">The value of this <see cref="GasGaugeNeedle"/>.</param>
+ public GasGaugeNeedle( string label, double val, Color color )
+ : base( label )
+ {
+ NeedleValue = val;
+ NeedleColor = color;
+ NeedleWidth = Default.NeedleWidth;
+ SweepAngle = 0f;
+ _border = new Border( Default.BorderColor, Default.BorderWidth );
+ _labelDetail = new TextObj();
+ _labelDetail.FontSpec.Size = Default.FontSize;
+ _slicePath = null;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="ggn">The <see cref="GasGaugeNeedle"/> object from which to copy</param>
+ public GasGaugeNeedle( GasGaugeNeedle ggn )
+ : base( ggn )
+ {
+ NeedleValue = ggn.NeedleValue;
+ NeedleColor = ggn.NeedleColor;
+ NeedleWidth = ggn.NeedleWidth;
+ SweepAngle = ggn.SweepAngle;
+ _border = ggn.Border.Clone();
+ _labelDetail = ggn.LabelDetail.Clone();
+ _labelDetail.FontSpec.Size = ggn.LabelDetail.FontSpec.Size;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public GasGaugeNeedle Clone()
+ {
+ return new GasGaugeNeedle( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or Sets the NeedleWidth of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public float NeedleWidth
+ {
+ get { return _needleWidth; }
+ set { _needleWidth = value; }
+ }
+
+ /// <summary>
+ /// Gets or Sets the Border of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public Border Border
+ {
+ get { return ( _border ); }
+ set { _border = value; }
+ }
+
+ /// <summary>
+ /// Gets or Sets the SlicePath of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public GraphicsPath SlicePath
+ {
+ get { return _slicePath; }
+ }
+
+ /// <summary>
+ /// Gets or Sets the LableDetail of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public TextObj LabelDetail
+ {
+ get { return _labelDetail; }
+ set { _labelDetail = value; }
+ }
+
+
+ /// <summary>
+ /// Gets or Sets the NeedelColor of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public Color NeedleColor
+ {
+ get { return _color; }
+ set
+ {
+ _color = value;
+ Fill = new Fill( _color );
+ }
+ }
+
+ /// <summary>
+ /// Gets or Sets the Fill of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Private property that Gets or Sets the SweepAngle of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ private float SweepAngle
+ {
+ get { return _sweepAngle; }
+ set { _sweepAngle = value; }
+ }
+
+ /// <summary>
+ /// Gets or Sets the NeedleValue of this <see cref="GasGaugeNeedle"/>
+ /// </summary>
+ public double NeedleValue
+ {
+ get { return ( _needleValue ); }
+ set { _needleValue = value > 0 ? value : 0; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return true;
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected GasGaugeNeedle( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _labelDetail = (TextObj)info.GetValue( "labelDetail", typeof( TextObj ) );
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+ _border = (Border)info.GetValue( "border", typeof( Border ) );
+ _needleValue = info.GetDouble( "needleValue" );
+ _boundingRectangle = (RectangleF)info.GetValue( "boundingRectangle", typeof( RectangleF ) );
+ _slicePath = (GraphicsPath)info.GetValue( "slicePath", typeof( GraphicsPath ) );
+ _sweepAngle = (float)info.GetDouble( "sweepAngle" );
+ _color = (Color)info.GetValue( "color", typeof( Color ) );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "labelDetail", _labelDetail );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "needleValue", _needleValue );
+ info.AddValue( "boundingRectangle", _boundingRectangle );
+ info.AddValue( "slicePath", _slicePath );
+ info.AddValue( "sweepAngle", _sweepAngle );
+ }
+
+ #endregion
+
+ #region Default
+
+ /// <summary>
+ /// Specify the default property values for the <see cref="GasGaugeNeedle"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default width of the gas gauge needle. Units are points, scaled according
+ /// to <see cref="PaneBase.CalcScaleFactor" />
+ /// </summary>
+ public static float NeedleWidth = 10.0F;
+
+ /// <summary>
+ /// The default pen width to be used for drawing the border around the GasGaugeNeedle
+ /// (<see cref="ZedGraph.LineBase.Width"/> property). Units are points.
+ /// </summary>
+ public static float BorderWidth = 1.0F;
+
+ /// <summary>
+ /// The default border mode for GasGaugeNeedle (<see cref="ZedGraph.LineBase.IsVisible"/>
+ /// property).
+ /// true to display frame around GasGaugeNeedle, false otherwise
+ /// </summary>
+ public static bool IsBorderVisible = true;
+
+ /// <summary>
+ /// The default color for drawing frames around GasGaugeNeedle
+ /// (<see cref="ZedGraph.LineBase.Color"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Gray;
+
+ /// <summary>
+ /// The default fill type for filling the GasGaugeNeedle.
+ /// </summary>
+ public static FillType FillType = FillType.Brush;
+
+ /// <summary>
+ /// The default color for filling in the GasGaugeNeedle
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.Empty;
+
+ /// <summary>
+ /// The default custom brush for filling in the GasGaugeNeedle.
+ /// (<see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null;
+
+ /// <summary>
+ ///Default value for controlling <see cref="GasGaugeNeedle"/> display.
+ /// </summary>
+ public static bool isVisible = true;
+
+// /// <summary>
+// /// Default value for <see cref="GasGaugeNeedle.LabelType"/>.
+// /// </summary>
+// public static PieLabelType LabelType = PieLabelType.Name;
+
+ /// <summary>
+ /// The default font size for <see cref="GasGaugeNeedle.LabelDetail"/> entries
+ /// (<see cref="ZedGraph.FontSpec.Size"/> property). Units are
+ /// in points (1/72 inch).
+ /// </summary>
+ public static float FontSize = 10;
+ }
+
+ #endregion Defaults
+
+ #region Methods
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="GasGaugeNeedle"/> item to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">Not used for rendering GasGaugeNeedle</param>
+ /// <param name="scaleFactor">Not used for rendering GasGaugeNeedle</param>
+ public override void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0 )
+ {
+ _slicePath = null;
+ }
+ else
+ {
+ CalcRectangle( g, pane, scaleFactor, pane.Chart._rect );
+
+ _slicePath = new GraphicsPath();
+
+ if ( !_isVisible )
+ return;
+
+ RectangleF tRect = _boundingRectangle;
+
+ if ( tRect.Width >= 1 && tRect.Height >= 1 )
+ {
+ SmoothingMode sMode = g.SmoothingMode;
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+
+ Matrix matrix = new Matrix();
+
+ matrix.Translate( tRect.X + ( tRect.Width / 2 ), tRect.Y + ( tRect.Height / 2 ), MatrixOrder.Prepend );
+
+ PointF[] pts = new PointF[2];
+ pts[0] = new PointF( ( ( tRect.Height * .10f ) / 2.0f ) * (float)Math.Cos( -SweepAngle * Math.PI / 180.0f ),
+ ( ( tRect.Height * .10f ) / 2.0f ) * (float)Math.Sin( -SweepAngle * Math.PI / 180.0f ) );
+ pts[1] = new PointF( ( tRect.Width / 2.0f ) * (float)Math.Cos( -SweepAngle * Math.PI / 180.0f ),
+ ( tRect.Width / 2.0f ) * (float)Math.Sin( -SweepAngle * Math.PI / 180.0f ) );
+
+ matrix.TransformPoints( pts );
+
+ Pen p = new Pen( NeedleColor, ( ( tRect.Height * .10f ) / 2.0f ) );
+ p.EndCap = LineCap.ArrowAnchor;
+ g.DrawLine( p, pts[0].X, pts[0].Y, pts[1].X, pts[1].Y );
+
+ //Fill center 10% with Black dot;
+ Fill f = new Fill( Color.Black );
+ RectangleF r = new RectangleF( ( tRect.X + ( tRect.Width / 2 ) ) - 1.0f, ( tRect.Y + ( tRect.Height / 2 ) ) - 1.0f, 1.0f, 1.0f );
+ r.Inflate( ( tRect.Height * .10f ), ( tRect.Height * .10f ) );
+ Brush b = f.MakeBrush( r );
+ g.FillPie( b, r.X, r.Y, r.Width, r.Height, 0.0f, -180.0f );
+
+ Pen borderPen = new Pen( Color.White, 2.0f );
+ g.DrawPie( borderPen, r.X, r.Y, r.Width, r.Height, 0.0f, -180.0f );
+
+ g.SmoothingMode = sMode;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Render the label for this <see cref="GasGaugeNeedle"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">Bounding rectangle for this <see cref="GasGaugeNeedle"/>.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public override void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ if ( !_isVisible )
+ return;
+
+ float yMid = rect.Top + rect.Height / 2.0F;
+
+ Pen pen = new Pen( NeedleColor, pane.ScaledPenWidth( NeedleWidth / 2, scaleFactor ) );
+ pen.StartCap = LineCap.Round;
+ pen.EndCap = LineCap.ArrowAnchor;
+ pen.DashStyle = DashStyle.Solid;
+ g.DrawLine( pen, rect.Left, yMid, rect.Right, yMid );
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ public override bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = String.Empty;
+ return false;
+ }
+
+ /// <summary>
+ /// Calculate the values needed to properly display this <see cref="GasGaugeNeedle"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public static void CalculateGasGaugeParameters( GraphPane pane )
+ {
+ //loop thru slices and get total value and maxDisplacement
+ double minVal = double.MaxValue;
+ double maxVal = double.MinValue;
+ foreach ( CurveItem curve in pane.CurveList )
+ if ( curve is GasGaugeRegion )
+ {
+ GasGaugeRegion ggr = (GasGaugeRegion)curve;
+ if ( maxVal < ggr.MaxValue )
+ maxVal = ggr.MaxValue;
+
+ if ( minVal > ggr.MinValue )
+ minVal = ggr.MinValue;
+ }
+
+ //Set Needle Sweep angle values here based on the min and max values of the GasGuage
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ if ( curve is GasGaugeNeedle )
+ {
+ GasGaugeNeedle ggn = (GasGaugeNeedle)curve;
+ float sweep = ( (float)ggn.NeedleValue - (float)minVal ) /
+ ( (float)maxVal - (float)minVal ) * 180.0f;
+ ggn.SweepAngle = sweep;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculate the <see cref="RectangleF"/> that will be used to define the bounding rectangle of
+ /// the GasGaugeNeedle.
+ /// </summary>
+ /// <remarks>This rectangle always lies inside of the <see cref="Chart.Rect"/>, and it is
+ /// normally a square so that the pie itself is not oval-shaped.</remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="chartRect">The <see cref="RectangleF"/> (normally the <see cref="Chart.Rect"/>)
+ /// that bounds this pie.</param>
+ /// <returns></returns>
+ public static RectangleF CalcRectangle( Graphics g, GraphPane pane, float scaleFactor, RectangleF chartRect )
+ {
+ RectangleF nonExpRect = chartRect;
+
+ if ( ( 2 * nonExpRect.Height ) > nonExpRect.Width )
+ {
+ //Scale based on width
+ float percentS = ( ( nonExpRect.Height * 2 ) - nonExpRect.Width ) / ( nonExpRect.Height * 2 );
+ nonExpRect.Height = ( ( nonExpRect.Height * 2 ) - ( ( nonExpRect.Height * 2 ) * percentS ) );
+ }
+ else
+ {
+ nonExpRect.Height = nonExpRect.Height * 2;
+ }
+
+ nonExpRect.Width = nonExpRect.Height;
+
+ float xDelta = ( chartRect.Width / 2 ) - ( nonExpRect.Width / 2 );
+
+ //Align Horizontally
+ nonExpRect.X += xDelta;
+
+ nonExpRect.Inflate( -(float)0.05F * nonExpRect.Height, -(float)0.05 * nonExpRect.Width );
+
+ GasGaugeNeedle.CalculateGasGaugeParameters( pane );
+
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ if ( curve is GasGaugeNeedle )
+ {
+ GasGaugeNeedle ggn = (GasGaugeNeedle)curve;
+ ggn._boundingRectangle = nonExpRect;
+ }
+ }
+
+ return nonExpRect;
+
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/GasGaugeRegion.cs b/ZedGraph/GasGaugeRegion.cs
new file mode 100644
index 0000000..eddb866
--- /dev/null
+++ b/ZedGraph/GasGaugeRegion.cs
@@ -0,0 +1,597 @@
+//============================================================================
+//GasGaugeRegion Class
+//Copyright � 2006 Jay Mistry
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System.Runtime.Serialization;
+using System.Drawing.Drawing2D;
+using System;
+using System.Text;
+using System.Drawing;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class representing a region on the GasGuage chart
+ /// <see cref="GasGaugeRegion"/>s.
+ /// </summary>
+ /// <author> Jay Mistry </author>
+ /// <version> $Revision: 1.2 $ $Date: 2007-07-30 05:26:23 $ </version>
+ [Serializable]
+ public class GasGaugeRegion : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Defines the minimum value of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private double _minValue;
+
+ /// <summary>
+ /// Defines the maximum value of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private double _maxValue;
+
+ /// <summary>
+ /// Defines the Color of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private Color _color;
+
+ /// <summary>
+ /// Internally calculated; Start angle of this pie that defines this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private float _startAngle;
+
+ /// <summary>
+ /// Internally calculated; Sweep angle of this pie that defines this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private float _sweepAngle;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="GasGaugeRegion"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+
+ /// <summary>
+ /// A <see cref="ZedGraph.TextObj"/> which will customize the label display of this
+ /// <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private TextObj _labelDetail;
+
+ /// <summary>
+ /// Private field that stores the <see cref="Border"/> class that defines the
+ /// properties of the border around this <see cref="GasGaugeRegion"/>. Use the public
+ /// property <see cref="Border"/> to access this value.
+ /// </summary>
+ private Border _border;
+
+ /// <summary>
+ /// The bounding rectangle for this <see cref="GasGaugeRegion"/>.
+ /// </summary>
+ private RectangleF _boundingRectangle;
+
+ /// <summary>
+ /// Private field to hold the GraphicsPath of this <see cref="GasGaugeRegion"/> to be
+ /// used for 'hit testing'.
+ /// </summary>
+ private GraphicsPath _slicePath;
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected GasGaugeRegion( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _labelDetail = (TextObj)info.GetValue( "labelDetail", typeof( TextObj ) );
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+ _border = (Border)info.GetValue( "border", typeof( Border ) );
+ _color = (Color)info.GetValue( "color", typeof( Color ) );
+ _minValue = info.GetDouble( "minValue" );
+ _maxValue = info.GetDouble( "maxValue" );
+ _startAngle = (float)info.GetDouble( "startAngle" );
+ _sweepAngle = (float)info.GetDouble( "sweepAngle" );
+ _boundingRectangle = (RectangleF)info.GetValue( "boundingRectangle", typeof( RectangleF ) );
+ _slicePath = (GraphicsPath)info.GetValue( "slicePath", typeof( GraphicsPath ) );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "labelDetail", _labelDetail );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "color", _color );
+ info.AddValue( "border", _border );
+ info.AddValue( "minVal", _minValue );
+ info.AddValue( "maxVal", _maxValue );
+ info.AddValue( "startAngle", _startAngle );
+ info.AddValue( "sweepAngle", _sweepAngle );
+ info.AddValue( "boundingRectangle", _boundingRectangle );
+ info.AddValue( "slicePath", _slicePath );
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Create a new <see cref="GasGaugeRegion"/>
+ /// </summary>
+ /// <param name="label">The value associated with this <see cref="GasGaugeRegion"/> instance.</param>
+ /// <param name="color">The display color for this <see cref="GasGaugeRegion"/> instance.</param>
+ /// <param name="minVal">The minimum value of this <see cref="GasGaugeNeedle"/>.</param>
+ /// <param name="maxVal">The maximum value of this <see cref="GasGaugeNeedle"/>.</param>
+ public GasGaugeRegion( string label, double minVal, double maxVal, Color color )
+ : base( label )
+ {
+ MinValue = minVal;
+ MaxValue = maxVal;
+ RegionColor = color;
+ StartAngle = 0f;
+ SweepAngle = 0f;
+ _border = new Border( Default.BorderColor, Default.BorderWidth );
+ _labelDetail = new TextObj();
+ _labelDetail.FontSpec.Size = Default.FontSize;
+ _slicePath = null;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="ggr">The <see cref="GasGaugeRegion"/> object from which to copy</param>
+ public GasGaugeRegion( GasGaugeRegion ggr )
+ : base( ggr )
+ {
+ _minValue = ggr._minValue;
+ _maxValue = ggr._maxValue;
+ _color = ggr._color;
+ _startAngle = ggr._startAngle;
+ _sweepAngle = ggr._sweepAngle;
+ _border = ggr._border.Clone();
+ _labelDetail = ggr._labelDetail.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public GasGaugeRegion Clone()
+ {
+ return new GasGaugeRegion( this );
+ }
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the SlicePath of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public GraphicsPath SlicePath
+ {
+ get { return _slicePath; }
+ }
+
+ /// <summary>
+ /// Gets or sets the LabelDetail of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public TextObj LabelDetail
+ {
+ get { return _labelDetail; }
+ set { _labelDetail = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Border of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public Border Border
+ {
+ get { return ( _border ); }
+ set { _border = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the RegionColor of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public Color RegionColor
+ {
+ get { return _color; }
+ set
+ {
+ _color = value;
+ Fill = new Fill( _color );
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Fill of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the SweepAngle of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private float SweepAngle
+ {
+ get { return _sweepAngle; }
+ set { _sweepAngle = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the StartAngle of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ private float StartAngle
+ {
+ get { return ( _startAngle ); }
+ set { _startAngle = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the MinValue of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public double MinValue
+ {
+ get { return ( _minValue ); }
+ set { _minValue = value > 0 ? value : 0; }
+ }
+
+ /// <summary>
+ /// Gets or sets the MaxValue of this <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public double MaxValue
+ {
+ get { return ( _maxValue ); }
+ set { _maxValue = value > 0 ? value : 0; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return true;
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// Specify the default property values for the <see cref="GasGaugeRegion"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default border pen width for the <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public static float BorderWidth = 1.0F;
+
+ /// <summary>
+ /// The default fill type for the <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public static FillType FillType = FillType.Brush;
+
+ /// <summary>
+ /// The default value for the visibility of the <see cref="GasGaugeRegion"/> border.
+ /// </summary>
+ public static bool IsBorderVisible = true;
+
+ /// <summary>
+ /// The default value for the color of the <see cref="GasGaugeRegion"/> border
+ /// </summary>
+ public static Color BorderColor = Color.Gray;
+
+ /// <summary>
+ /// The default value for the color of the <see cref="GasGaugeRegion"/> fill
+ /// </summary>
+ public static Color FillColor = Color.Empty;
+
+ /// <summary>
+ /// The default value for the fill brush of the <see cref="GasGaugeRegion"/>
+ /// </summary>
+ public static Brush FillBrush = null;
+
+ /// <summary>
+ /// The default value for the visibility of the <see cref="GasGaugeRegion"/> fill.
+ /// </summary>
+ public static bool isVisible = true;
+
+// public static PieLabelType LabelType = PieLabelType.Name;
+
+ /// <summary>
+ /// The default value for the font size of the <see cref="GasGaugeRegion"/> labels.
+ /// </summary>
+ public static float FontSize = 10;
+ }
+
+ #endregion Defaults
+
+ #region Methods
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="GasGaugeRegion"/> item to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">Not used for rendering GasGaugeNeedle</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public override void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0 )
+ {
+ _slicePath = null;
+ }
+ else
+ {
+ CalcRectangle( g, pane, scaleFactor, pane.Chart._rect );
+
+ _slicePath = new GraphicsPath();
+
+ if ( !_isVisible )
+ return;
+
+ RectangleF tRect = _boundingRectangle;
+
+ if ( tRect.Width >= 1 && tRect.Height >= 1 )
+ {
+ SmoothingMode sMode = g.SmoothingMode;
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+
+ _slicePath.AddPie( tRect.X, tRect.Y, tRect.Width, tRect.Height,
+ -0.0f, -180.0f );
+
+ g.FillPie( Fill.MakeBrush( _boundingRectangle ), tRect.X, tRect.Y, tRect.Width, tRect.Height, -StartAngle, -SweepAngle );
+
+ if ( this.Border.IsVisible )
+ {
+ Pen borderPen = _border.GetPen( pane, scaleFactor );
+ g.DrawPie( borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height,
+ -0.0f, -180.0f );
+ borderPen.Dispose();
+ }
+
+ g.SmoothingMode = sMode;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Render the label for this <see cref="GasGaugeRegion"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">Bounding rectangle for this <see cref="GasGaugeRegion"/>.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public override void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ if ( !_isVisible )
+ return;
+
+ // Fill the slice
+ if ( _fill.IsVisible )
+ {
+ // just avoid height/width being less than 0.1 so GDI+ doesn't cry
+ using ( Brush brush = _fill.MakeBrush( rect ) )
+ {
+ g.FillRectangle( brush, rect );
+ //brush.Dispose();
+ }
+ }
+
+ // Border the bar
+ if ( !_border.Color.IsEmpty )
+ _border.Draw( g, pane, scaleFactor, rect );
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ public override bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = String.Empty;
+ return false;
+ }
+
+ /// <summary>
+ /// Calculate the values needed to properly display this <see cref="GasGaugeRegion"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public static void CalculateGasGuageParameters( GraphPane pane )
+ {
+ //loop thru slices and get total value and maxDisplacement
+ double minVal = double.MaxValue;
+ double maxVal = double.MinValue;
+ foreach ( CurveItem curve in pane.CurveList )
+ if ( curve is GasGaugeRegion )
+ {
+ GasGaugeRegion ggr = (GasGaugeRegion)curve;
+ if ( maxVal < ggr.MaxValue )
+ maxVal = ggr.MaxValue;
+
+ if ( minVal > ggr.MinValue )
+ minVal = ggr.MinValue;
+ }
+
+ //Calculate start and sweep angles for each of the GasGaugeRegion based on teh min and max value
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ if ( curve is GasGaugeRegion )
+ {
+ GasGaugeRegion ggr = (GasGaugeRegion)curve;
+ float start = ( (float)ggr.MinValue - (float)minVal ) / ( (float)maxVal - (float)minVal ) * 180.0f;
+ float sweep = ( (float)ggr.MaxValue - (float)minVal ) / ( (float)maxVal - (float)minVal ) * 180.0f;
+ sweep = sweep - start;
+
+ Fill f = new Fill( Color.White, ggr.RegionColor, -( sweep / 2f ) );
+ ggr.Fill = f;
+
+ ggr.StartAngle = start;
+ ggr.SweepAngle = sweep;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculate the <see cref="RectangleF"/> that will be used to define the bounding rectangle of
+ /// the GasGaugeNeedle.
+ /// </summary>
+ /// <remarks>This rectangle always lies inside of the <see cref="Chart.Rect"/>, and it is
+ /// normally a square so that the pie itself is not oval-shaped.</remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="chartRect">The <see cref="RectangleF"/> (normally the <see cref="Chart.Rect"/>)
+ /// that bounds this pie.</param>
+ /// <returns></returns>
+ public static RectangleF CalcRectangle( Graphics g, GraphPane pane, float scaleFactor, RectangleF chartRect )
+ {
+ RectangleF nonExpRect = chartRect;
+
+ if ( ( 2 * nonExpRect.Height ) > nonExpRect.Width )
+ {
+ //Scale based on width
+ float percentS = ( ( nonExpRect.Height * 2 ) - nonExpRect.Width ) / ( nonExpRect.Height * 2 );
+ nonExpRect.Height = ( ( nonExpRect.Height * 2 ) - ( ( nonExpRect.Height * 2 ) * percentS ) );
+ }
+ else
+ {
+ nonExpRect.Height = nonExpRect.Height * 2;
+ }
+
+ nonExpRect.Width = nonExpRect.Height;
+
+ float xDelta = ( chartRect.Width / 2 ) - ( nonExpRect.Width / 2 );
+
+ //Align Horizontally
+ nonExpRect.X += xDelta;
+ //nonExpRect.Y += -(float)0.025F * nonExpRect.Height;
+ //nonExpRect.Y += ((chartRect.Height) - (nonExpRect.Height / 2)) - 10.0f;
+
+ nonExpRect.Inflate( -(float)0.05F * nonExpRect.Height, -(float)0.05 * nonExpRect.Width );
+
+ GasGaugeRegion.CalculateGasGuageParameters( pane );
+
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ if ( curve is GasGaugeRegion )
+ {
+ GasGaugeRegion gg = (GasGaugeRegion)curve;
+ gg._boundingRectangle = nonExpRect;
+ }
+ }
+
+ return nonExpRect;
+
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/GraphObj.cs b/ZedGraph/GraphObj.cs
new file mode 100644
index 0000000..ad8859d
--- /dev/null
+++ b/ZedGraph/GraphObj.cs
@@ -0,0 +1,504 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An abstract base class that represents a text object on the graph. A list of
+ /// <see cref="GraphObj"/> objects is maintained by the
+ /// <see cref="GraphObjList"/> collection class.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ abstract public class GraphObj : ISerializable, ICloneable
+ {
+ #region Fields
+ /// <summary>
+ /// Protected field that stores the location of this <see cref="GraphObj"/>.
+ /// Use the public property <see cref="Location"/> to access this value.
+ /// </summary>
+ protected Location _location;
+
+ /// <summary>
+ /// Protected field that determines whether or not this <see cref="GraphObj"/>
+ /// is visible in the graph. Use the public property <see cref="IsVisible"/> to
+ /// access this value.
+ /// </summary>
+ protected bool _isVisible;
+
+ /// <summary>
+ /// Protected field that determines whether or not the rendering of this <see cref="GraphObj"/>
+ /// will be clipped to the ChartRect. Use the public property <see cref="IsClippedToChartRect"/> to
+ /// access this value.
+ /// </summary>
+ protected bool _isClippedToChartRect;
+
+ /// <summary>
+ /// A tag object for use by the user. This can be used to store additional
+ /// information associated with the <see cref="GraphObj"/>. ZedGraph does
+ /// not use this value for any purpose.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if you are going to Serialize ZedGraph data, then any type
+ /// that you store in <see cref="Tag"/> must be a serializable type (or
+ /// it will cause an exception).
+ /// </remarks>
+ public object Tag;
+
+ /// <summary>
+ /// Internal field that determines the z-order "depth" of this
+ /// item relative to other graphic objects. Use the public property
+ /// <see cref="ZOrder"/> to access this value.
+ /// </summary>
+ internal ZOrder _zOrder;
+
+ /// <summary>
+ /// Internal field that stores the hyperlink information for this object.
+ /// </summary>
+ internal Link _link;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="GraphObj"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default text item properties
+ /// <summary>
+ /// Default value for the vertical <see cref="GraphObj"/>
+ /// text alignment (<see cref="GraphObj.Location"/> property).
+ /// This is specified
+ /// using the <see cref="AlignV"/> enum type.
+ /// </summary>
+ public static AlignV AlignV = AlignV.Center;
+ /// <summary>
+ /// Default value for the horizontal <see cref="GraphObj"/>
+ /// text alignment (<see cref="GraphObj.Location"/> property).
+ /// This is specified
+ /// using the <see cref="AlignH"/> enum type.
+ /// </summary>
+ public static AlignH AlignH = AlignH.Center;
+ /// <summary>
+ /// The default coordinate system to be used for defining the
+ /// <see cref="GraphObj"/> location coordinates
+ /// (<see cref="GraphObj.Location"/> property).
+ /// </summary>
+ /// <value> The coordinate system is defined with the <see cref="CoordType"/>
+ /// enum</value>
+ public static CoordType CoordFrame = CoordType.AxisXYScale;
+ /// <summary>
+ /// The default value for <see cref="GraphObj.IsClippedToChartRect"/>.
+ /// </summary>
+ public static bool IsClippedToChartRect = false;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// The <see cref="ZedGraph.Location"/> struct that describes the location
+ /// for this <see cref="GraphObj"/>.
+ /// </summary>
+ public Location Location
+ {
+ get { return _location; }
+ set { _location = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines the z-order "depth" of this
+ /// item relative to other graphic objects.
+ /// </summary>
+ /// <remarks>Note that this controls the z-order with respect to
+ /// other elements such as <see cref="CurveItem"/>'s, <see cref="Axis"/>
+ /// objects, etc. The order of <see cref="GraphObj"/> objects having
+ /// the same <see cref="ZedGraph.ZOrder"/> value is controlled by their order in
+ /// the <see cref="GraphObjList"/>. The first <see cref="GraphObj"/>
+ /// in the list is drawn in front of other <see cref="GraphObj"/>
+ /// objects having the same <see cref="ZedGraph.ZOrder"/> value.</remarks>
+ public ZOrder ZOrder
+ {
+ get { return _zOrder; }
+ set { _zOrder = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if this <see cref="GraphObj"/> will be
+ /// visible in the graph. true displays the item, false hides it.
+ /// </summary>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the rendering of this <see cref="GraphObj"/>
+ /// will be clipped to the <see cref="Chart.Rect"/>.
+ /// </summary>
+ /// <value>true to clip the <see cref="GraphObj"/> to the <see cref="Chart.Rect"/> bounds,
+ /// false to leave it unclipped.</value>
+ public bool IsClippedToChartRect
+ {
+ get { return _isClippedToChartRect; }
+ set { _isClippedToChartRect = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the hyperlink information for this <see cref="GraphObj" />.
+ /// </summary>
+ // /// <seealso cref="ZedGraph.Web.IsImageMap" />
+ public Link Link
+ {
+ get { return _link; }
+ set { _link = value; }
+ }
+
+ /// <summary>
+ /// true if the <see cref="ZOrder" /> of this object is set to put it in front
+ /// of the <see cref="CurveItem" /> data points.
+ /// </summary>
+ public bool IsInFrontOfData
+ {
+ get
+ {
+ return _zOrder == ZOrder.A_InFront ||
+ _zOrder == ZOrder.B_BehindLegend ||
+ _zOrder == ZOrder.C_BehindChartBorder;
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <overloads>
+ /// Constructors for the <see cref="GraphObj"/> class.
+ /// </overloads>
+ /// <summary>
+ /// Default constructor that sets all <see cref="GraphObj"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public GraphObj() :
+ this( 0, 0, Default.CoordFrame, Default.AlignH, Default.AlignV )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that sets all <see cref="GraphObj"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="x">The x position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the <see cref="AlignH"/>
+ /// property.</param>
+ /// <param name="y">The y position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the
+ /// <see cref="AlignV"/> property.</param>
+ public GraphObj( double x, double y ) :
+ this( x, y, Default.CoordFrame, Default.AlignH, Default.AlignV )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="GraphObj"/> with the specified
+ /// coordinates and all other properties to defaults as specified
+ /// in the <see cref="Default"/> class..
+ /// </summary>
+ /// <remarks>
+ /// The four coordinates define the starting point and ending point for
+ /// <see cref="ArrowObj"/>'s, or the topleft and bottomright points for
+ /// <see cref="ImageObj"/>'s. For <see cref="GraphObj"/>'s that only require
+ /// one point, the <see paramref="x2"/> and <see paramref="y2"/> values
+ /// will be ignored. The units of the coordinates are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property.
+ /// </remarks>
+ /// <param name="x">The x position of the item.</param>
+ /// <param name="y">The y position of the item.</param>
+ /// <param name="x2">The x2 position of the item.</param>
+ /// <param name="y2">The x2 position of the item.</param>
+ public GraphObj( double x, double y, double x2, double y2 ) :
+ this( x, y, x2, y2, Default.CoordFrame, Default.AlignH, Default.AlignV )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="GraphObj"/> with the specified
+ /// position and <see cref="CoordType"/>. Other properties are set to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <remarks>
+ /// The two coordinates define the location point for the object.
+ /// The units of the coordinates are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property.
+ /// </remarks>
+ /// <param name="x">The x position of the item. The item will be
+ /// aligned to this position based on the <see cref="AlignH"/>
+ /// property.</param>
+ /// <param name="y">The y position of the item. The item will be
+ /// aligned to this position based on the
+ /// <see cref="AlignV"/> property.</param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum value that
+ /// indicates what type of coordinate system the x and y parameters are
+ /// referenced to.</param>
+ public GraphObj( double x, double y, CoordType coordType ) :
+ this( x, y, coordType, Default.AlignH, Default.AlignV )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="GraphObj"/> with the specified
+ /// position, <see cref="CoordType"/>, <see cref="AlignH"/>, and <see cref="AlignV"/>.
+ /// Other properties are set to default values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <remarks>
+ /// The two coordinates define the location point for the object.
+ /// The units of the coordinates are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property.
+ /// </remarks>
+ /// <param name="x">The x position of the item. The item will be
+ /// aligned to this position based on the <see cref="AlignH"/>
+ /// property.</param>
+ /// <param name="y">The y position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the
+ /// <see cref="AlignV"/> property.</param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum value that
+ /// indicates what type of coordinate system the x and y parameters are
+ /// referenced to.</param>
+ /// <param name="alignH">The <see cref="ZedGraph.AlignH"/> enum that specifies
+ /// the horizontal alignment of the object with respect to the (x,y) location</param>
+ /// <param name="alignV">The <see cref="ZedGraph.AlignV"/> enum that specifies
+ /// the vertical alignment of the object with respect to the (x,y) location</param>
+ public GraphObj( double x, double y, CoordType coordType, AlignH alignH, AlignV alignV )
+ {
+ _isVisible = true;
+ _isClippedToChartRect = Default.IsClippedToChartRect;
+ this.Tag = null;
+ _zOrder = ZOrder.A_InFront;
+ _location = new Location( x, y, coordType, alignH, alignV );
+ _link = new Link();
+ }
+
+ /// <summary>
+ /// Constructor that creates a <see cref="GraphObj"/> with the specified
+ /// position, <see cref="CoordType"/>, <see cref="AlignH"/>, and <see cref="AlignV"/>.
+ /// Other properties are set to default values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <remarks>
+ /// The four coordinates define the starting point and ending point for
+ /// <see cref="ArrowObj"/>'s, or the topleft and bottomright points for
+ /// <see cref="ImageObj"/>'s. For <see cref="GraphObj"/>'s that only require
+ /// one point, the <see paramref="x2"/> and <see paramref="y2"/> values
+ /// will be ignored. The units of the coordinates are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property.
+ /// </remarks>
+ /// <param name="x">The x position of the item.</param>
+ /// <param name="y">The y position of the item.</param>
+ /// <param name="x2">The x2 position of the item.</param>
+ /// <param name="y2">The x2 position of the item.</param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum value that
+ /// indicates what type of coordinate system the x and y parameters are
+ /// referenced to.</param>
+ /// <param name="alignH">The <see cref="ZedGraph.AlignH"/> enum that specifies
+ /// the horizontal alignment of the object with respect to the (x,y) location</param>
+ /// <param name="alignV">The <see cref="ZedGraph.AlignV"/> enum that specifies
+ /// the vertical alignment of the object with respect to the (x,y) location</param>
+ public GraphObj( double x, double y, double x2, double y2, CoordType coordType,
+ AlignH alignH, AlignV alignV )
+ {
+ _isVisible = true;
+ _isClippedToChartRect = Default.IsClippedToChartRect;
+ this.Tag = null;
+ _zOrder = ZOrder.A_InFront;
+ _location = new Location( x, y, x2, y2, coordType, alignH, alignV );
+ _link = new Link();
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="GraphObj"/> object from which to copy</param>
+ public GraphObj( GraphObj rhs )
+ {
+ // Copy value types
+ _isVisible = rhs.IsVisible;
+ _isClippedToChartRect = rhs._isClippedToChartRect;
+ _zOrder = rhs.ZOrder;
+
+ // copy reference types by cloning
+ if ( rhs.Tag is ICloneable )
+ this.Tag = ((ICloneable) rhs.Tag).Clone();
+ else
+ this.Tag = rhs.Tag;
+
+ _location = rhs.Location.Clone();
+ _link = rhs._link.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of Clone.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method must be called with an explicit cast to ICloneable, and
+ /// that it is inherently virtual. For example:
+ /// <code>
+ /// ParentClass foo = new ChildClass();
+ /// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
+ /// </code>
+ /// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
+ /// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
+ /// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
+ /// </remarks>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
+ //return new PaneBase( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ /// <remarks>
+ /// schema changed to 2 when isClippedToChartRect was added.
+ /// </remarks>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected GraphObj( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _location = (Location) info.GetValue( "location", typeof(Location) );
+ _isVisible = info.GetBoolean( "isVisible" );
+ Tag = info.GetValue( "Tag", typeof(object) );
+ _zOrder = (ZOrder) info.GetValue( "zOrder", typeof(ZOrder) );
+
+ _isClippedToChartRect = info.GetBoolean( "isClippedToChartRect" );
+ _link = (Link) info.GetValue( "link", typeof( Link ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "location", _location );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "Tag", Tag );
+ info.AddValue( "zOrder", _zOrder );
+
+ info.AddValue( "isClippedToChartRect", _isClippedToChartRect );
+ info.AddValue( "link", _link );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this <see cref="GraphObj"/> object to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="PaneBase"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ abstract public void Draw( Graphics g, PaneBase pane, float scaleFactor );
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="GraphObj"/>.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="PaneBase"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ virtual public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ GraphPane gPane = pane as GraphPane;
+
+ if ( gPane != null && _isClippedToChartRect && !gPane.Chart.Rect.Contains( pt ) )
+ return false;
+
+ return true;
+ }
+
+ /// <summary>
+ /// Determines the shape type and Coords values for this GraphObj
+ /// </summary>
+ abstract public void GetCoords( PaneBase pane, Graphics g, float scaleFactor,
+ out string shape, out string coords );
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/GraphObjList.cs b/ZedGraph/GraphObjList.cs
new file mode 100644
index 0000000..0529cf4
--- /dev/null
+++ b/ZedGraph/GraphObjList.cs
@@ -0,0 +1,304 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="TextObj"/> objects
+ /// to be displayed on the graph.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class GraphObjList : List<GraphObj>, ICloneable
+ {
+ #region Constructors
+ /// <summary>
+ /// Default constructor for the <see cref="GraphObjList"/> collection class
+ /// </summary>
+ public GraphObjList()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="GraphObjList"/> object from which to copy</param>
+ public GraphObjList( GraphObjList rhs )
+ {
+ foreach ( GraphObj item in rhs )
+ this.Add( (GraphObj) ((ICloneable)item).Clone() );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public GraphObjList Clone()
+ {
+ return new GraphObjList( this );
+ }
+
+
+ #endregion
+
+ #region Methods
+/*
+ /// <summary>
+ /// Indexer to access the specified <see cref="GraphObj"/> object by its ordinal
+ /// position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="GraphObj"/> object to be accessed.</param>
+ /// <value>A <see cref="GraphObj"/> object reference.</value>
+ public GraphObj this[ int index ]
+ {
+ get { return( (GraphObj) List[index] ); }
+ set { List[index] = value; }
+ }
+*/
+ /// <summary>
+ /// Indexer to access the specified <see cref="GraphObj"/> object by its <see cref="GraphObj.Tag"/>.
+ /// Note that the <see cref="GraphObj.Tag"/> must be a <see cref="String"/> type for this method
+ /// to work.
+ /// </summary>
+ /// <param name="tag">The <see cref="String"/> type tag to search for.</param>
+ /// <value>A <see cref="GraphObj"/> object reference.</value>
+ /// <seealso cref="IndexOfTag"/>
+ public GraphObj this[string tag]
+ {
+ get
+ {
+ int index = IndexOfTag( tag );
+ if ( index >= 0 )
+ return( this[index] );
+ else
+ return null;
+ }
+ }
+/*
+ /// <summary>
+ /// Add a <see cref="GraphObj"/> object to the <see cref="GraphObjList"/>
+ /// collection at the end of the list.
+ /// </summary>
+ /// <param name="item">A reference to the <see cref="GraphObj"/> object to
+ /// be added</param>
+ /// <seealso cref="IList.Add"/>
+ public GraphObj Add( GraphObj item )
+ {
+ List.Add( item );
+ return item;
+ }
+
+ /// <summary>
+ /// Insert a <see cref="GraphObj"/> object into the collection
+ /// at the specified zero-based index location.
+ /// </summary>
+ /// <param name="index">The zero-based index location for insertion.</param>
+ /// <param name="item">The <see cref="GraphObj"/> object that is to be
+ /// inserted.</param>
+ /// <seealso cref="IList.Insert"/>
+ public void Insert( int index, GraphObj item )
+ {
+ List.Insert( index, item );
+ }
+*/
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="GraphObj"/> with the specified <see cref="GraphObj.Tag"/>.
+ /// </summary>
+ /// <remarks>In order for this method to work, the <see cref="GraphObj.Tag"/>
+ /// property must be of type <see cref="String"/>.</remarks>
+ /// <param name="tag">The <see cref="String"/> tag that is in the
+ /// <see cref="GraphObj.Tag"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="GraphObj"/>,
+ /// or -1 if the <see cref="GraphObj"/> is not in the list</returns>
+ public int IndexOfTag( string tag )
+ {
+ int index = 0;
+ foreach ( GraphObj p in this )
+ {
+ if ( p.Tag is string &&
+ String.Compare( (string) p.Tag, tag, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Move the position of the object at the specified index
+ /// to the new relative position in the list.</summary>
+ /// <remarks>For Graphic type objects, this method controls the
+ /// Z-Order of the items. Objects at the beginning of the list
+ /// appear in front of objects at the end of the list.</remarks>
+ /// <param name="index">The zero-based index of the object
+ /// to be moved.</param>
+ /// <param name="relativePos">The relative number of positions to move
+ /// the object. A value of -1 will move the
+ /// object one position earlier in the list, a value
+ /// of 1 will move it one position later. To move an item to the
+ /// beginning of the list, use a large negative value (such as -999).
+ /// To move it to the end of the list, use a large positive value.
+ /// </param>
+ /// <returns>The new position for the object, or -1 if the object
+ /// was not found.</returns>
+ public int Move( int index, int relativePos )
+ {
+ if ( index < 0 || index >= Count )
+ return -1;
+
+ GraphObj graphObj = this[index];
+ this.RemoveAt( index );
+
+ index += relativePos;
+ if ( index < 0 )
+ index = 0;
+ if ( index > Count )
+ index = Count;
+
+ Insert( index, graphObj );
+ return index;
+ }
+
+ #endregion
+
+ #region Render Methods
+
+ /// <summary>
+ /// Render text to the specified <see cref="Graphics"/> device
+ /// by calling the Draw method of each <see cref="GraphObj"/> object in
+ /// the collection.
+ /// </summary>
+ /// <remarks>This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphPane"/> object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="zOrder">A <see cref="ZOrder"/> enumeration that controls
+ /// the placement of this <see cref="GraphObj"/> relative to other
+ /// graphic objects. The order of <see cref="GraphObj"/>'s with the
+ /// same <see cref="ZOrder"/> value is control by their order in
+ /// this <see cref="GraphObjList"/>.</param>
+ public void Draw( Graphics g, PaneBase pane, float scaleFactor,
+ ZOrder zOrder )
+ {
+ // Draw the items in reverse order, so the last items in the
+ // list appear behind the first items (consistent with
+ // CurveList)
+ for ( int i=this.Count-1; i>=0; i-- )
+ {
+ GraphObj item = this[i];
+ if ( item.ZOrder == zOrder && item.IsVisible )
+ {
+ Region region = null;
+ if ( item.IsClippedToChartRect && pane is GraphPane )
+ {
+ region = g.Clip.Clone();
+ g.SetClip( ((GraphPane)pane).Chart._rect );
+ }
+
+ item.Draw( g, pane, scaleFactor );
+
+ if ( item.IsClippedToChartRect && pane is GraphPane )
+ g.Clip = region;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Determine if a mouse point is within any <see cref="GraphObj"/>, and if so,
+ /// return the index number of the the <see cref="GraphObj"/>.
+ /// </summary>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="index">The index number of the <see cref="TextObj"/>
+ /// that is under the mouse point. The <see cref="TextObj"/> object is
+ /// accessible via the <see cref="GraphObjList" /> indexer property.
+ /// </param>
+ /// <returns>true if the mouse point is within a <see cref="GraphObj"/> bounding
+ /// box, false otherwise.</returns>
+ /// <seealso cref="GraphPane.FindNearestObject"/>
+ public bool FindPoint( PointF mousePt, PaneBase pane, Graphics g, float scaleFactor, out int index )
+ {
+ index = -1;
+
+ // Search in reverse direction to honor the Z-order
+ for ( int i=Count-1; i>=0; i-- )
+ {
+ if ( this[i].PointInBox( mousePt, pane, g, scaleFactor ) )
+ {
+ if ( ( index >= 0 && this[i].ZOrder > this[index].ZOrder ) || index < 0 )
+ index = i;
+ }
+ }
+
+ if ( index >= 0 )
+ return true;
+ else
+ return false;
+ }
+
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/GraphPane.cs b/ZedGraph/GraphPane.cs
new file mode 100644
index 0000000..8887465
--- /dev/null
+++ b/ZedGraph/GraphPane.cs
@@ -0,0 +1,2329 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Drawing.Imaging;
+using System.Windows.Forms;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.ComponentModel;
+
+namespace ZedGraph
+{
+ // <summary>
+ // <c>ZedGraph</c> is a class library and UserControl (<see cref="ZedGraphControl"/>) that display
+ // 2D line graphs of user specified data. The <c>ZedGraph</c> namespace includes all functionality
+ // required to draw, modify, and update the graph.
+ // </summary>
+
+ /// <summary>
+ /// Class <see cref="GraphPane"/> encapsulates the graph pane, which is all display elements
+ /// associated with an individual graph.
+ /// </summary>
+ /// <remarks>This class is the outside "wrapper"
+ /// for the ZedGraph classes, and provides the interface to access the attributes
+ /// of the graph. You can have multiple graphs in the same document or form,
+ /// just instantiate multiple GraphPane's.
+ /// </remarks>
+ ///
+ /// <author> John Champion modified by Jerry Vos </author>
+ /// <version> $Revision: 3.81 $ $Date: 2007-09-30 07:44:11 $ </version>
+ [Serializable]
+ public class GraphPane : PaneBase, ICloneable, ISerializable
+ {
+
+ #region Events
+
+ /// <summary>
+ /// A delegate to provide notification through the <see cref="AxisChangeEvent" />
+ /// when <see cref="AxisChange()" /> is called.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> for which AxisChange() has
+ /// been called.</param>
+ /// <seealso cref="AxisChangeEvent" />
+ public delegate void AxisChangeEventHandler( GraphPane pane );
+
+ /// <summary>
+ /// Subscribe to this event to be notified when <see cref="AxisChange()" /> is called.
+ /// </summary>
+ public event AxisChangeEventHandler AxisChangeEvent;
+
+ #endregion
+
+ #region Private Fields
+
+ // Item subclasses ////////////////////////////////////////////////////////////////////
+
+ /// <summary>Private field instance of the <see cref="ZedGraph.XAxis"/> class. Use the
+ /// public property <see cref="GraphPane.XAxis"/> to access this class.</summary>
+ private XAxis _xAxis;
+ /// <summary>Private field instance of the <see cref="ZedGraph.XAxis"/> class. Use the
+ /// public property <see cref="GraphPane.X2Axis"/> to access this class.</summary>
+ private X2Axis _x2Axis;
+ /// <summary>Private field instance of the <see cref="ZedGraph.YAxisList"/> class. Use the
+ /// public property <see cref="GraphPane.YAxisList"/> to access this class.</summary>
+ private YAxisList _yAxisList;
+ /// <summary>Private field instance of the <see cref="ZedGraph.Y2AxisList"/> class. Use the
+ /// public property <see cref="GraphPane.Y2AxisList"/> to access this class.</summary>
+ private Y2AxisList _y2AxisList;
+ /// <summary>Private field instance of the <see cref="ZedGraph.CurveList"/> class. Use the
+ /// public property <see cref="GraphPane.CurveList"/> to access this class.</summary>
+ private CurveList _curveList;
+
+ /// <summary>
+ /// private value that contains a <see cref="ZoomStateStack"/>, which stores prior
+ /// <see cref="ZoomState"/> objects containing scale range information. This enables
+ /// zooming and panning functionality for the <see cref="ZedGraphControl"/>.
+ /// </summary>
+ private ZoomStateStack _zoomStack;
+
+ // Chart Properties //////////////////////////////////////////////////////////////
+
+ internal Chart _chart;
+
+ internal BarSettings _barSettings;
+
+ /// <summary>Private field that determines whether or not initial zero values will
+ /// be included or excluded when determining the Y or Y2 axis scale range.
+ /// Use the public property <see cref="IsIgnoreInitial"/> to access
+ /// this value. </summary>
+ private bool _isIgnoreInitial;
+ /// <summary>Private field that determines whether or not initial
+ /// <see cref="PointPairBase.Missing"/> values will cause the line segments of
+ /// a curve to be discontinuous. If this field is true, then the curves
+ /// will be plotted as continuous lines as if the Missing values did not
+ /// exist.
+ /// Use the public property <see cref="IsIgnoreMissing"/> to access
+ /// this value. </summary>
+ private bool _isIgnoreMissing;
+ /// <summary> private field that determines if the auto-scaled axis ranges will subset the
+ /// data points based on any manually set scale range values. Use the public property
+ /// <see cref="IsBoundedRanges"/> to access this value.</summary>
+ /// <remarks>The bounds provide a means to subset the data. For example, if all the axes are set to
+ /// autoscale, then the full range of data are used. But, if the XAxis.Min and XAxis.Max values
+ /// are manually set, then the Y data range will reflect the Y values within the bounds of
+ /// XAxis.Min and XAxis.Max.</remarks>
+ private bool _isBoundedRanges;
+
+ /// <summary>
+ /// private field that determines if ZedGraph should modify the scale ranges for the Y and Y2
+ /// axes such that the number of steps, and therefore the grid lines, line up. Use the
+ /// public property <see cref="IsAlignGrids" /> to acccess this value.
+ /// </summary>
+ private bool _isAlignGrids;
+
+
+ /// <summary>Private field that determines how the <see cref="LineItem"/>
+ /// graphs will be displayed. See the <see cref="ZedGraph.LineType"/> enum
+ /// for the individual types available.
+ /// To access this value, use the public property <see cref="LineType"/>.
+ /// </summary>
+ /// <seealso cref="Default.LineType"/>
+ private LineType _lineType;
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="GraphPane"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ /// <summary>
+ /// The default settings for the <see cref="Axis"/> scale ignore initial
+ /// zero values option (<see cref="GraphPane.IsIgnoreInitial"/> property).
+ /// true to have the auto-scale-range code ignore the initial data points
+ /// until the first non-zero Y value, false otherwise.
+ /// </summary>
+ public static bool IsIgnoreInitial = false;
+ /// <summary>
+ /// The default settings for the <see cref="Axis"/> scale bounded ranges option
+ /// (<see cref="GraphPane.IsBoundedRanges"/> property).
+ /// true to have the auto-scale-range code subset the data according to any
+ /// manually set scale values, false otherwise.
+ /// </summary>
+ public static bool IsBoundedRanges = false;
+
+ /// <summary>The default value for the <see cref="GraphPane.LineType"/> property, which
+ /// determines if the lines are drawn in normal or "stacked" mode. See the
+ /// <see cref="ZedGraph.LineType"/> for more information.
+ /// </summary>
+ /// <seealso cref="GraphPane.LineType"/>
+ public static LineType LineType = LineType.Normal;
+ /// <summary>
+ /// The default width of a bar cluster
+ /// on a <see cref="Bar"/> graph. This value only applies to
+ /// <see cref="Bar"/> graphs, and only when the
+ /// <see cref="Axis.Type"/> is <see cref="AxisType.Linear"/>,
+ /// <see cref="AxisType.Log"/> or <see cref="AxisType.Date"/>.
+ /// This dimension is expressed in terms of X scale user units.
+ /// </summary>
+ /// <seealso cref="ZedGraph.BarSettings.Default.MinClusterGap"/>
+ /// <seealso cref="ZedGraph.BarSettings.MinBarGap"/>
+ public static double ClusterScaleWidth = 1.0;
+ /// <summary>
+ /// The tolerance that is applied to the
+ /// <see cref="GraphPane.FindNearestPoint(PointF,out CurveItem,out int)"/> routine.
+ /// If a given curve point is within this many pixels of the mousePt, the curve
+ /// point is considered to be close enough for selection as a nearest point
+ /// candidate.
+ /// </summary>
+ public static double NearestTol = 7.0;
+
+ }
+ #endregion
+
+ #region Class Instance Properties
+ /// <summary>
+ /// Gets or sets the list of <see cref="CurveItem"/> items for this <see cref="GraphPane"/>
+ /// </summary>
+ /// <value>A reference to a <see cref="CurveList"/> collection object</value>
+ public CurveList CurveList
+ {
+ get { return _curveList; }
+ set { _curveList = value; }
+ }
+ /// <summary>
+ /// Accesses the <see cref="XAxis"/> for this graph
+ /// </summary>
+ /// <value>A reference to a <see cref="XAxis"/> object</value>
+ public XAxis XAxis
+ {
+ get { return _xAxis; }
+ }
+ /// <summary>
+ /// Accesses the <see cref="X2Axis"/> for this graph
+ /// </summary>
+ /// <value>A reference to a <see cref="X2Axis"/> object</value>
+ public X2Axis X2Axis
+ {
+ get { return _x2Axis; }
+ }
+ /// <summary>
+ /// Accesses the primary <see cref="YAxis"/> for this graph
+ /// </summary>
+ /// <value>A reference to a <see cref="YAxis"/> object</value>
+ /// <seealso cref="YAxisList" />
+ /// <seealso cref="Y2AxisList" />
+ public YAxis YAxis
+ {
+ get { return _yAxisList[0] as YAxis; }
+ }
+ /// <summary>
+ /// Accesses the primary <see cref="Y2Axis"/> for this graph
+ /// </summary>
+ /// <value>A reference to a <see cref="Y2Axis"/> object</value>
+ /// <seealso cref="YAxisList" />
+ /// <seealso cref="Y2AxisList" />
+ public Y2Axis Y2Axis
+ {
+ get { return _y2AxisList[0] as Y2Axis; }
+ }
+
+ /// <summary>
+ /// Gets the collection of Y axes that belong to this <see cref="GraphPane" />.
+ /// </summary>
+ public YAxisList YAxisList
+ {
+ get { return _yAxisList; }
+ }
+ /// <summary>
+ /// Gets the collection of Y2 axes that belong to this <see cref="GraphPane" />.
+ /// </summary>
+ public Y2AxisList Y2AxisList
+ {
+ get { return _y2AxisList; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Chart" /> instance for this <see cref="GraphPane" />.
+ /// </summary>
+ public Chart Chart
+ {
+ get { return _chart; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="BarSettings" /> instance for this <see cref="GraphPane" />,
+ /// which stores the global properties for bar type charts.
+ /// </summary>
+ public BarSettings BarSettings
+ {
+ get { return _barSettings; }
+ }
+
+ #endregion
+
+ #region General Properties
+
+ /// <summary>
+ /// Gets or sets a boolean value that affects the data range that is considered
+ /// for the automatic scale ranging.
+ /// </summary>
+ /// <remarks>If true, then initial data points where the Y value
+ /// is zero are not included when automatically determining the scale <see cref="Scale.Min"/>,
+ /// <see cref="Scale.Max"/>, and <see cref="Scale.MajorStep"/> size.
+ /// All data after the first non-zero Y value are included.
+ /// </remarks>
+ /// <seealso cref="Default.IsIgnoreInitial"/>
+ [Bindable( true ), Browsable( true ), Category( "Display" ), NotifyParentProperty( true )]
+ [Description("Determines whether the auto-ranged scale will include all data points" +
+ " or just the visible data points")]
+ public bool IsIgnoreInitial
+ {
+ get { return _isIgnoreInitial; }
+ set { _isIgnoreInitial = value; }
+ }
+ /// <summary> Gets or sets a boolean value that determines if the auto-scaled axis ranges will
+ /// subset the data points based on any manually set scale range values.</summary>
+ /// <remarks>The bounds provide a means to subset the data. For example, if all the axes are set to
+ /// autoscale, then the full range of data are used. But, if the XAxis.Min and XAxis.Max values
+ /// are manually set, then the Y data range will reflect the Y values within the bounds of
+ /// XAxis.Min and XAxis.Max. Set to true to subset the data, or false to always include
+ /// all data points when calculating scale ranges.</remarks>
+ public bool IsBoundedRanges
+ {
+ get { return _isBoundedRanges; }
+ set { _isBoundedRanges = value; }
+ }
+ /// <summary>Gets or sets a value that determines whether or not initial
+ /// <see cref="PointPairBase.Missing"/> values will cause the line segments of
+ /// a curve to be discontinuous.
+ /// </summary>
+ /// <remarks>If this field is true, then the curves
+ /// will be plotted as continuous lines as if the Missing values did not exist.
+ /// Use the public property <see cref="IsIgnoreMissing"/> to access
+ /// this value. </remarks>
+ public bool IsIgnoreMissing
+ {
+ get { return _isIgnoreMissing; }
+ set { _isIgnoreMissing = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if ZedGraph should modify the scale ranges
+ /// for the Y and Y2 axes such that the number of major steps, and therefore the
+ /// major grid lines, line up.
+ /// </summary>
+ /// <remarks>
+ /// This property affects the way that <see cref="AxisChange()" /> selects the scale
+ /// ranges for the Y and Y2 axes. It applies to the scale ranges of all Y and Y2 axes,
+ /// but only if the <see cref="Scale.MaxAuto" /> is set to true.<br />
+ /// </remarks>
+ public bool IsAlignGrids
+ {
+ get { return _isAlignGrids; }
+ set { _isAlignGrids = value; }
+ }
+
+ /// <summary>Determines how the <see cref="LineItem"/>
+ /// graphs will be displayed. See the <see cref="ZedGraph.LineType"/> enum
+ /// for the individual types available.
+ /// </summary>
+ /// <seealso cref="Default.LineType"/>
+ public LineType LineType
+ {
+ get { return _lineType; }
+ set { _lineType = value; }
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether or not the <see cref="ZoomStateStack" /> for
+ /// this <see cref="GraphPane" /> is empty. Note that this value is only used for
+ /// the <see cref="ZedGraphControl" />.
+ /// </summary>
+ public bool IsZoomed
+ {
+ get { return !_zoomStack.IsEmpty; }
+ }
+
+ /// <summary>
+ /// Gets a reference to the <see cref="ZoomStateStack" /> for this <see cref="GraphPane" />.
+ /// </summary>
+ public ZoomStateStack ZoomStack
+ {
+ get { return _zoomStack; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor. Sets the <see cref="PaneBase.Rect"/> to (0, 0, 500, 375), and
+ /// sets the <see cref="PaneBase.Title"/> and <see cref="Axis.Title"/> values to empty
+ /// strings.
+ /// </summary>
+ public GraphPane()
+ : this( new RectangleF( 0, 0, 500, 375 ), "", "", "" )
+ {
+ }
+
+ /// <summary>
+ /// Constructor for the <see cref="GraphPane"/> object. This routine will
+ /// initialize all member variables and classes, setting appropriate default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="rect"> A rectangular screen area where the graph is to be displayed.
+ /// This area can be any size, and can be resize at any time using the
+ /// <see cref="PaneBase.Rect"/> property.
+ /// </param>
+ /// <param name="title">The <see cref="PaneBase.Title"/> for this <see cref="GraphPane"/></param>
+ /// <param name="xTitle">The <see cref="Axis.Title"/> for the <see cref="XAxis"/></param>
+ /// <param name="yTitle">The <see cref="Axis.Title"/> for the <see cref="YAxis"/></param>
+ public GraphPane( RectangleF rect, string title,
+ string xTitle, string yTitle )
+ : base( title, rect )
+ {
+ _xAxis = new XAxis( xTitle );
+ _x2Axis = new X2Axis( "" );
+
+ _yAxisList = new YAxisList();
+ _y2AxisList = new Y2AxisList();
+
+ _yAxisList.Add( new YAxis( yTitle ) );
+ _y2AxisList.Add( new Y2Axis( string.Empty ) );
+
+ _curveList = new CurveList();
+ _zoomStack = new ZoomStateStack();
+
+ _isIgnoreInitial = Default.IsIgnoreInitial;
+ _isBoundedRanges = Default.IsBoundedRanges;
+ _isAlignGrids = false;
+
+ _chart = new Chart();
+
+ _barSettings = new BarSettings( this );
+
+ _lineType = Default.LineType;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The GraphPane object from which to copy</param>
+ public GraphPane( GraphPane rhs )
+ : base( rhs )
+ {
+ // copy values for all the value types
+ _isIgnoreInitial = rhs.IsIgnoreInitial;
+ _isBoundedRanges = rhs._isBoundedRanges;
+ _isAlignGrids = rhs._isAlignGrids;
+
+ _chart = rhs._chart.Clone();
+
+ _barSettings = new BarSettings( rhs._barSettings, this );
+
+ _lineType = rhs.LineType;
+
+
+ // copy all the reference types with deep copies
+ _xAxis = new XAxis( rhs.XAxis );
+ _x2Axis = new X2Axis( rhs.X2Axis );
+
+ _yAxisList = new YAxisList( rhs._yAxisList );
+ _y2AxisList = new Y2AxisList( rhs._y2AxisList );
+
+ _curveList = new CurveList( rhs.CurveList );
+ _zoomStack = new ZoomStateStack( rhs._zoomStack );
+
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public GraphPane Clone()
+ {
+ return new GraphPane( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ //changed to 2 when yAxisList and y2AxisList were added
+ //changed to 3 when chart object was added
+ //changed to 10 when refactored to version 5
+ //changed to 11 when added x2axis
+ public const int schema2 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected GraphPane( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _xAxis = (XAxis)info.GetValue( "xAxis", typeof( XAxis ) );
+ if ( sch >= 11 )
+ _x2Axis = (X2Axis)info.GetValue( "x2Axis", typeof( X2Axis ) );
+ else
+ _x2Axis = new X2Axis( "" );
+
+ _yAxisList = (YAxisList)info.GetValue( "yAxisList", typeof( YAxisList ) );
+ _y2AxisList = (Y2AxisList)info.GetValue( "y2AxisList", typeof( Y2AxisList ) );
+
+ _curveList = (CurveList)info.GetValue( "curveList", typeof( CurveList ) );
+
+ _chart = (Chart) info.GetValue( "chart", typeof( Chart ) );
+
+ _barSettings = (BarSettings)info.GetValue( "barSettings", typeof( BarSettings ) );
+ _barSettings._ownerPane = this;
+
+ _isIgnoreInitial = info.GetBoolean( "isIgnoreInitial" );
+ _isBoundedRanges = info.GetBoolean( "isBoundedRanges" );
+ _isIgnoreMissing = info.GetBoolean( "isIgnoreMissing" );
+ _isAlignGrids = info.GetBoolean( "isAlignGrids" );
+
+ _lineType = (LineType)info.GetValue( "lineType", typeof( LineType ) );
+
+ _zoomStack = new ZoomStateStack();
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+
+ info.AddValue( "xAxis", _xAxis );
+ info.AddValue( "x2Axis", _x2Axis );
+ info.AddValue( "yAxisList", _yAxisList );
+ info.AddValue( "y2AxisList", _y2AxisList );
+ info.AddValue( "curveList", _curveList );
+
+ info.AddValue( "chart", _chart );
+
+ info.AddValue( "barSettings", _barSettings );
+
+ info.AddValue( "isIgnoreInitial", _isIgnoreInitial );
+ info.AddValue( "isBoundedRanges", _isBoundedRanges );
+ info.AddValue( "isIgnoreMissing", _isIgnoreMissing );
+ info.AddValue( "isAlignGrids", _isAlignGrids );
+
+ info.AddValue( "lineType", _lineType );
+ }
+
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// AxisChange causes the axes scale ranges to be recalculated based on the current data range.
+ /// </summary>
+ /// <remarks>
+ /// There is no obligation to call AxisChange() for manually scaled axes. AxisChange() is only
+ /// intended to handle auto scaling operations. Call this function anytime you change, add, or
+ /// remove curve data to insure that the scale range of the axes are appropriate for the data range.
+ /// This method calculates
+ /// a scale minimum, maximum, and step size for each axis based on the current curve data.
+ /// Only the axis attributes (min, max, step) that are set to auto-range
+ /// (<see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>, <see cref="Scale.MajorStepAuto"/>)
+ /// will be modified. You must call <see cref="Control.Invalidate()"/> after calling
+ /// AxisChange to make sure the display gets updated.<br />
+ /// This overload of AxisChange just uses the default Graphics instance for the screen.
+ /// If you have a Graphics instance available from your Windows Form, you should use
+ /// the <see cref="AxisChange(Graphics)" /> overload instead.
+ /// </remarks>
+ public void AxisChange()
+ {
+ using ( Graphics g = Graphics.FromHwnd( IntPtr.Zero ) )
+ AxisChange( g );
+ }
+
+ /// <summary>
+ /// AxisChange causes the axes scale ranges to be recalculated based on the current data range.
+ /// </summary>
+ /// <remarks>
+ /// There is no obligation to call AxisChange() for manually scaled axes. AxisChange() is only
+ /// intended to handle auto scaling operations. Call this function anytime you change, add, or
+ /// remove curve data to insure that the scale range of the axes are appropriate for the data range.
+ /// This method calculates
+ /// a scale minimum, maximum, and step size for each axis based on the current curve data.
+ /// Only the axis attributes (min, max, step) that are set to auto-range
+ /// (<see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>, <see cref="Scale.MajorStepAuto"/>)
+ /// will be modified. You must call
+ /// <see cref="Control.Invalidate()"/> after calling AxisChange to make sure the display gets updated.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public void AxisChange( Graphics g )
+ {
+ //double xMin, xMax, yMin, yMax, y2Min, y2Max;
+
+ // Get the scale range of the data (all curves)
+ _curveList.GetRange( /* out xMin, out xMax, out yMin,
+ out yMax, out y2Min, out y2Max, */
+ _isIgnoreInitial, _isBoundedRanges, this );
+
+ // Determine the scale factor
+ float scaleFactor = this.CalcScaleFactor();
+
+ // For pie charts, go ahead and turn off the axis displays if it's only pies
+ if ( this.CurveList.IsPieOnly )
+ {
+ //don't want to display axis or border if there's only pies
+ this.XAxis.IsVisible = false;
+ this.X2Axis.IsVisible = false;
+ this.YAxis.IsVisible = false;
+ this.Y2Axis.IsVisible = false;
+ _chart.Border.IsVisible = false;
+ //this.Legend.Position = LegendPos.TopCenter;
+ }
+
+ // Set the ClusterScaleWidth, if needed
+ //_barSettings.CalcClusterScaleWidth();
+ if ( _barSettings._clusterScaleWidthAuto )
+ _barSettings._clusterScaleWidth = 1.0;
+
+ // if the ChartRect is not yet determined, then pick a scale based on a default ChartRect
+ // size (using 75% of Rect -- code is in Axis.CalcMaxLabels() )
+ // With the scale picked, call CalcChartRect() so calculate a real ChartRect
+ // then let the scales re-calculate to make sure that the assumption was ok
+ if ( _chart._isRectAuto )
+ {
+ PickScale( g, scaleFactor );
+
+ _chart._rect = CalcChartRect( g );
+ //this.pieRect = PieItem.CalcPieRect( g, this, scaleFactor, this.chartRect );
+ }
+
+ // Pick new scales based on the range
+ PickScale( g, scaleFactor );
+
+ // Set the ClusterScaleWidth, if needed
+ _barSettings.CalcClusterScaleWidth();
+
+ // Trigger the AxisChangeEvent
+ if ( this.AxisChangeEvent != null )
+ this.AxisChangeEvent( this );
+
+ }
+
+ private void PickScale( Graphics g, float scaleFactor )
+ {
+ int maxTics = 0;
+
+ _xAxis._scale.PickScale( this, g, scaleFactor );
+ _x2Axis._scale.PickScale( this, g, scaleFactor );
+
+ foreach ( Axis axis in _yAxisList )
+ {
+ axis._scale.PickScale( this, g, scaleFactor );
+ if ( axis._scale.MaxAuto )
+ {
+ int nTics = axis._scale.CalcNumTics();
+ maxTics = nTics > maxTics ? nTics : maxTics;
+ }
+ }
+ foreach ( Axis axis in _y2AxisList )
+ {
+ axis._scale.PickScale( this, g, scaleFactor );
+ if ( axis._scale.MaxAuto )
+ {
+ int nTics = axis._scale.CalcNumTics();
+ maxTics = nTics > maxTics ? nTics : maxTics;
+ }
+ }
+
+ if ( _isAlignGrids )
+ {
+ foreach ( Axis axis in _yAxisList )
+ ForceNumTics( axis, maxTics );
+
+ foreach ( Axis axis in _y2AxisList )
+ ForceNumTics( axis, maxTics );
+ }
+
+ }
+
+ private void ForceNumTics( Axis axis, int numTics )
+ {
+ if ( axis._scale.MaxAuto )
+ {
+ int nTics = axis._scale.CalcNumTics();
+ if ( nTics < numTics )
+ axis._scale._maxLinearized += axis._scale._majorStep * ( numTics - nTics );
+ }
+ }
+
+ /// <summary>
+ /// Draw all elements in the <see cref="GraphPane"/> to the specified graphics device.
+ /// </summary>
+ /// <remarks>This method
+ /// should be part of the Paint() update process. Calling this routine will redraw all
+ /// features of the graph. No preparation is required other than an instantiated
+ /// <see cref="GraphPane"/> object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public override void Draw( Graphics g )
+ {
+ // Calculate the chart rect, deducting the area for the scales, titles, legend, etc.
+ //int hStack;
+ //float legendWidth, legendHeight;
+
+ // Draw the pane border & background fill, the title, and the GraphObj objects that lie at
+ // ZOrder.G_BehindAll
+ base.Draw( g );
+
+ if ( _rect.Width <= 1 || _rect.Height <= 1 )
+ return;
+
+ // Clip everything to the rect
+ g.SetClip( _rect );
+
+ // calculate scaleFactor on "normal" pane size (BaseDimension)
+ float scaleFactor = this.CalcScaleFactor();
+
+
+ // if the size of the ChartRect is determined automatically, then do so
+ // otherwise, calculate the legendrect, scalefactor, hstack, and legendwidth parameters
+ // but leave the ChartRect alone
+ if ( _chart._isRectAuto )
+ {
+ _chart._rect = CalcChartRect( g, scaleFactor );
+ //this.pieRect = PieItem.CalcPieRect( g, this, scaleFactor, this.chartRect );
+ }
+ else
+ CalcChartRect( g, scaleFactor );
+
+ // do a sanity check on the ChartRect
+ if ( _chart._rect.Width < 1 || _chart._rect.Height < 1 )
+ return;
+
+ // Draw the graph features only if there is at least one curve with data
+ // if ( _curveList.HasData() &&
+ // Go ahead and draw the graph, even without data. This makes the control
+ // version still look like a graph before it is fully set up
+ bool showGraf = AxisRangesValid();
+
+ // Setup the axes for graphing - This setup must be done before
+ // the GraphObj's are drawn so that the Transform functions are
+ // ready. Also, this should be done before CalcChartRect so that the
+ // Axis.Cross - shift parameter can be calculated.
+ _xAxis.Scale.SetupScaleData( this, _xAxis );
+ _x2Axis.Scale.SetupScaleData( this, _x2Axis );
+ foreach ( Axis axis in _yAxisList )
+ axis.Scale.SetupScaleData( this, axis );
+ foreach ( Axis axis in _y2AxisList )
+ axis.Scale.SetupScaleData( this, axis );
+
+ // Draw the GraphItems that are behind the Axis objects
+ if ( showGraf )
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.G_BehindChartFill );
+
+ // Fill the axis background
+ _chart.Fill.Draw( g, _chart._rect );
+
+ if ( showGraf )
+ {
+ // Draw the GraphItems that are behind the CurveItems
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.F_BehindGrid );
+
+ DrawGrid( g, scaleFactor );
+
+ // Draw the GraphItems that are behind the CurveItems
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.E_BehindCurves );
+
+ // Clip the points to the actual plot area
+ g.SetClip( _chart._rect );
+ _curveList.Draw( g, this, scaleFactor );
+ g.SetClip( _rect );
+
+ }
+
+ if ( showGraf )
+ {
+ // Draw the GraphItems that are behind the Axis objects
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.D_BehindAxis );
+
+ // Draw the Axes
+ _xAxis.Draw( g, this, scaleFactor, 0.0f );
+ _x2Axis.Draw( g, this, scaleFactor, 0.0f );
+
+ float yPos = 0;
+ foreach ( Axis axis in _yAxisList )
+ {
+ axis.Draw( g, this, scaleFactor, yPos );
+ yPos += axis._tmpSpace;
+ }
+
+ yPos = 0;
+ foreach ( Axis axis in _y2AxisList )
+ {
+ axis.Draw( g, this, scaleFactor, yPos );
+ yPos += axis._tmpSpace;
+ }
+
+ // Draw the GraphItems that are behind the Axis border
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.C_BehindChartBorder );
+ }
+
+ // Border the axis itself
+ _chart.Border.Draw( g, this, scaleFactor, _chart._rect );
+
+ if ( showGraf )
+ {
+ // Draw the GraphItems that are behind the Legend object
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.B_BehindLegend );
+
+ _legend.Draw( g, this, scaleFactor );
+
+ // Draw the GraphItems that are in front of all other items
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.A_InFront );
+ }
+
+ // Reset the clipping
+ g.ResetClip();
+
+ // Reset scale data
+ // this sets the temp values to NaN to cause an exception if these values are
+ // being used improperly
+ // Don't do this, since the web control needs access
+ /*
+ _xAxis.Scale.ResetScaleData();
+ foreach ( Axis axis in _yAxisList )
+ axis.Scale.ResetScaleData();
+ foreach ( Axis axis in _y2AxisList )
+ axis.Scale.ResetScaleData();
+ */
+ }
+
+ internal void DrawGrid( Graphics g, float scaleFactor )
+ {
+ _xAxis.DrawGrid( g, this, scaleFactor, 0.0f );
+ _x2Axis.DrawGrid( g, this, scaleFactor, 0.0f );
+
+ float shiftPos = 0.0f;
+ foreach ( YAxis yAxis in _yAxisList )
+ {
+ yAxis.DrawGrid( g, this, scaleFactor, shiftPos );
+ shiftPos += yAxis._tmpSpace;
+ }
+
+ shiftPos = 0.0f;
+ foreach ( Y2Axis y2Axis in _y2AxisList )
+ {
+ y2Axis.DrawGrid( g, this, scaleFactor, shiftPos );
+ shiftPos += y2Axis._tmpSpace;
+ }
+ }
+
+ private bool AxisRangesValid()
+ {
+ bool showGraf = _xAxis._scale._min < _xAxis._scale._max &&
+ _x2Axis._scale._min < _x2Axis._scale._max;
+ foreach ( Axis axis in _yAxisList )
+ if ( axis._scale._min >= axis._scale._max )
+ showGraf = false;
+ foreach ( Axis axis in _y2AxisList )
+ if ( axis._scale._min >= axis._scale._max )
+ showGraf = false;
+
+ return showGraf;
+ }
+
+ /// <summary>
+ /// Calculate the <see cref="ZedGraph.Chart.Rect"/> based on the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <remarks>The ChartRect
+ /// is the plot area bounded by the axes, and the rect is the total area as
+ /// specified by the client application.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <returns>The calculated chart rect, in pixel coordinates.</returns>
+ public RectangleF CalcChartRect( Graphics g )
+ {
+ // Calculate the chart rect, deducting the area for the scales, titles, legend, etc.
+ //int hStack;
+ //float legendWidth, legendHeight;
+
+ return CalcChartRect( g, CalcScaleFactor() );
+ }
+
+ /// <summary>
+ /// Calculate the <see cref="ZedGraph.Chart.Rect"/> based on the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <remarks>The ChartRect
+ /// is the plot area bounded by the axes, and the rect is the total area as
+ /// specified by the client application.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <returns>The calculated chart rect, in pixel coordinates.</returns>
+
+ public RectangleF CalcChartRect( Graphics g, float scaleFactor )
+ {
+ // chart rect starts out at the full pane rect less the margins
+ // and less space for the Pane title
+ RectangleF clientRect = this.CalcClientRect( g, scaleFactor );
+
+ //float minSpaceX = 0;
+ //float minSpaceY = 0;
+ //float minSpaceY2 = 0;
+ float totSpaceY = 0;
+ //float spaceY2 = 0;
+
+ // actual minimum axis space for the left side of the chart rect
+ float minSpaceL = 0;
+ // actual minimum axis space for the right side of the chart rect
+ float minSpaceR = 0;
+ // actual minimum axis space for the bottom side of the chart rect
+ float minSpaceB = 0;
+ // actual minimum axis space for the top side of the chart rect
+ float minSpaceT = 0;
+
+ _xAxis.CalcSpace( g, this, scaleFactor, out minSpaceB );
+ _x2Axis.CalcSpace( g, this, scaleFactor, out minSpaceT );
+
+ //minSpaceB = _xAxis.tmpMinSpace;
+
+ foreach ( Axis axis in _yAxisList )
+ {
+ float fixedSpace;
+ float tmp = axis.CalcSpace( g, this, scaleFactor, out fixedSpace );
+ //if ( !axis.CrossAuto || axis.Cross < _xAxis.Min )
+ if ( axis.IsCrossShifted( this ) )
+ totSpaceY += tmp;
+
+ minSpaceL += fixedSpace;
+ }
+ foreach ( Axis axis in _y2AxisList )
+ {
+ float fixedSpace;
+ float tmp = axis.CalcSpace( g, this, scaleFactor, out fixedSpace );
+ //if ( !axis.CrossAuto || axis.Cross < _xAxis.Min )
+ if ( axis.IsCrossShifted( this ) )
+ totSpaceY += tmp;
+
+ minSpaceR += fixedSpace;
+ }
+
+ float spaceB = 0, spaceT = 0, spaceL = 0, spaceR = 0;
+
+ SetSpace( _xAxis, clientRect.Height - _xAxis._tmpSpace, ref spaceB, ref spaceT );
+// minSpaceT = Math.Max( minSpaceT, spaceT );
+ SetSpace( _x2Axis, clientRect.Height - _x2Axis._tmpSpace, ref spaceT, ref spaceB );
+ _xAxis._tmpSpace = spaceB;
+ _x2Axis._tmpSpace = spaceT;
+
+ float totSpaceL = 0;
+ float totSpaceR = 0;
+
+ foreach ( Axis axis in _yAxisList )
+ {
+ SetSpace( axis, clientRect.Width - totSpaceY, ref spaceL, ref spaceR );
+ minSpaceR = Math.Max( minSpaceR, spaceR );
+ totSpaceL += spaceL;
+ axis._tmpSpace = spaceL;
+ }
+ foreach ( Axis axis in _y2AxisList )
+ {
+ SetSpace( axis, clientRect.Width - totSpaceY, ref spaceR, ref spaceL );
+ minSpaceL = Math.Max( minSpaceL, spaceL );
+ totSpaceR += spaceR;
+ axis._tmpSpace = spaceR;
+ }
+
+ RectangleF tmpRect = clientRect;
+
+ totSpaceL = Math.Max( totSpaceL, minSpaceL );
+ totSpaceR = Math.Max( totSpaceR, minSpaceR );
+ spaceB = Math.Max( spaceB, minSpaceB );
+ spaceT = Math.Max( spaceT, minSpaceT );
+
+ tmpRect.X += totSpaceL;
+ tmpRect.Width -= totSpaceL + totSpaceR;
+ tmpRect.Height -= spaceT + spaceB;
+ tmpRect.Y += spaceT;
+
+ _legend.CalcRect( g, this, scaleFactor, ref tmpRect );
+
+ return tmpRect;
+ }
+
+ private void SetSpace( Axis axis, float clientSize, ref float spaceNorm, ref float spaceAlt )
+ {
+ //spaceNorm = 0;
+ //spaceAlt = 0;
+
+ float crossFrac = axis.CalcCrossFraction( this );
+ float crossPix = crossFrac * ( 1 + crossFrac ) * ( 1 + crossFrac * crossFrac ) * clientSize;
+
+ if ( !axis.IsPrimary( this ) && axis.IsCrossShifted( this ) )
+ axis._tmpSpace = 0;
+
+ if ( axis._tmpSpace < crossPix )
+ axis._tmpSpace = 0;
+ else if ( crossPix > 0 )
+ axis._tmpSpace -= crossPix;
+
+ if ( axis._scale._isLabelsInside && ( axis.IsPrimary( this ) || ( crossFrac != 0.0 && crossFrac != 1.0 ) ) )
+ spaceAlt = axis._tmpSpace;
+ else
+ spaceNorm = axis._tmpSpace;
+ }
+
+ /// <summary>
+ /// This method will set the <see cref="Axis.MinSpace"/> property for all three axes;
+ /// <see cref="XAxis"/>, <see cref="YAxis"/>, and <see cref="Y2Axis"/>.
+ /// </summary>
+ /// <remarks>The <see cref="Axis.MinSpace"/>
+ /// is calculated using the currently required space multiplied by a fraction
+ /// (<paramref>bufferFraction</paramref>).
+ /// The currently required space is calculated using <see cref="Axis.CalcSpace"/>, and is
+ /// based on current data ranges, font sizes, etc. The "space" is actually the amount of space
+ /// required to fit the tic marks, scale labels, and axis title.
+ /// The calculation is done by calling the <see cref="Axis.SetMinSpaceBuffer"/> method for
+ /// each <see cref="Axis"/>.
+ /// </remarks>
+ /// <param name="g">A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.</param>
+ /// <param name="bufferFraction">The amount of space to allocate for the axis, expressed
+ /// as a fraction of the currently required space. For example, a value of 1.2 would
+ /// allow for 20% extra above the currently required space.</param>
+ /// <param name="isGrowOnly">If true, then this method will only modify the <see cref="Axis.MinSpace"/>
+ /// property if the calculated result is more than the current value.</param>
+ public void SetMinSpaceBuffer( Graphics g, float bufferFraction, bool isGrowOnly )
+ {
+ _xAxis.SetMinSpaceBuffer( g, this, bufferFraction, isGrowOnly );
+ _x2Axis.SetMinSpaceBuffer( g, this, bufferFraction, isGrowOnly );
+ foreach ( Axis axis in _yAxisList )
+ axis.SetMinSpaceBuffer( g, this, bufferFraction, isGrowOnly );
+ foreach ( Axis axis in _y2AxisList )
+ axis.SetMinSpaceBuffer( g, this, bufferFraction, isGrowOnly );
+ }
+
+ #endregion
+
+ #region AddCurve Methods
+
+ /// <summary>
+ /// Add a curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (double arrays) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="x">An array of double precision X values (the
+ /// independent values) that define the curve.</param>
+ /// <param name="y">An array of double precision Y values (the
+ /// dependent values) that define the curve.</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddCurve(string,double[],double[],Color)"/> method.</returns>
+ public LineItem AddCurve( string label, double[] x, double[] y, Color color )
+ {
+ LineItem curve = new LineItem( label, x, y, color, SymbolType.Default );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddCurve(string,IPointList,Color)"/> method.</returns>
+ public LineItem AddCurve( string label, IPointList points, Color color )
+ {
+ LineItem curve = new LineItem( label, points, color, SymbolType.Default );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (double arrays) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="x">An array of double precision X values (the
+ /// independent values) that define the curve.</param>
+ /// <param name="y">An array of double precision Y values (the
+ /// dependent values) that define the curve.</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <param name="symbolType">A symbol type (<see cref="SymbolType"/>)
+ /// that will be used for this curve.</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddCurve(string,double[],double[],Color,SymbolType)"/> method.</returns>
+ public LineItem AddCurve( string label, double[] x, double[] y,
+ Color color, SymbolType symbolType )
+ {
+ LineItem curve = new LineItem( label, x, y, color, symbolType );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <param name="symbolType">A symbol type (<see cref="SymbolType"/>)
+ /// that will be used for this curve.</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddCurve(string,IPointList,Color,SymbolType)"/> method.</returns>
+ public LineItem AddCurve( string label, IPointList points,
+ Color color, SymbolType symbolType )
+ {
+ LineItem curve = new LineItem( label, points, color, symbolType );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a stick graph (<see cref="StickItem"/> object) to the plot with
+ /// the given data points (double arrays) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="x">An array of double precision X values (the
+ /// independent values) that define the curve.</param>
+ /// <param name="y">An array of double precision Y values (the
+ /// dependent values) that define the curve.</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>A <see cref="StickItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddStick(string,double[],double[],Color)"/> method.</returns>
+ public StickItem AddStick( string label, double[] x, double[] y, Color color )
+ {
+ StickItem curve = new StickItem( label, x, y, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a stick graph (<see cref="StickItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddStick(string,IPointList,Color)"/> method.</returns>
+ public StickItem AddStick( string label, IPointList points, Color color )
+ {
+ StickItem curve = new StickItem( label, points, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a candlestick graph (<see cref="OHLCBarItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// </summary>
+ /// <remarks>
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// Note that the <see cref="IPointList" />
+ /// should contain <see cref="StockPt" /> objects instead of <see cref="PointPair" />
+ /// objects in order to contain all the data values required for this curve type.
+ /// </remarks>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddOHLCBar(string,IPointList,Color)"/> method.</returns>
+ public OHLCBarItem AddOHLCBar( string label, IPointList points, Color color )
+ {
+ OHLCBarItem curve = new OHLCBarItem( label, points, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a japanesecandlestick graph (<see cref="JapaneseCandleStickItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// </summary>
+ /// <remarks>
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// Note that the <see cref="IPointList" />
+ /// should contain <see cref="StockPt" /> objects instead of <see cref="PointPair" />
+ /// objects in order to contain all the data values required for this curve type.
+ /// </remarks>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddJapaneseCandleStick(string,IPointList)"/> method.</returns>
+ public JapaneseCandleStickItem AddJapaneseCandleStick( string label, IPointList points )
+ {
+ JapaneseCandleStickItem curve = new JapaneseCandleStickItem( label, points );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add an error bar set (<see cref="ErrorBarItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="x">An array of double precision X values (the
+ /// independent values) that define the curve.</param>
+ /// <param name="y">An array of double precision Y values (the
+ /// dependent values) that define the curve.</param>
+ /// <param name="baseValue">An array of double precision values that define the
+ /// base value (the bottom) of the bars for this curve.
+ /// </param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>An <see cref="ErrorBarItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddErrorBar(string,IPointList,Color)"/> method.</returns>
+ public ErrorBarItem AddErrorBar( string label, double[] x, double[] y,
+ double[] baseValue, Color color )
+ {
+ ErrorBarItem curve = new ErrorBarItem( label, new PointPairList( x, y, baseValue ),
+ color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+ /// <summary>
+ /// Add an error bar set (<see cref="ErrorBarItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">The color to used for the curve line,
+ /// symbols, etc.</param>
+ /// <returns>An <see cref="ErrorBarItem"/> class for the newly created curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddErrorBar(string,IPointList,Color)"/> method.</returns>
+ public ErrorBarItem AddErrorBar( string label, IPointList points, Color color )
+ {
+ ErrorBarItem curve = new ErrorBarItem( label, points, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a bar type curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">The color to used to fill the bars</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created bar curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddBar(string,IPointList,Color)"/> method.</returns>
+ public BarItem AddBar( string label, IPointList points, Color color )
+ {
+ BarItem curve = new BarItem( label, points, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a bar type curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (double arrays) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="x">An array of double precision X values (the
+ /// independent values) that define the curve.</param>
+ /// <param name="y">An array of double precision Y values (the
+ /// dependent values) that define the curve.</param>
+ /// <param name="color">The color to used for the bars</param>
+ /// <returns>A <see cref="CurveItem"/> class for the newly created bar curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddBar(string,double[],double[],Color)"/> method.</returns>
+ public BarItem AddBar( string label, double[] x, double[] y, Color color )
+ {
+ BarItem curve = new BarItem( label, x, y, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a "High-Low" bar type curve (<see cref="HiLowBarItem"/> object) to the plot with
+ /// the given data points (double arrays) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="x">An array of double precision X values (the
+ /// independent values) that define the curve.</param>
+ /// <param name="y">An array of double precision Y values (the
+ /// dependent values) that define the curve.</param>
+ /// <param name="baseVal">An array of double precision values that define the
+ /// base value (the bottom) of the bars for this curve.
+ /// </param>
+ /// <param name="color">The color to used for the bars</param>
+ /// <returns>A <see cref="HiLowBarItem"/> class for the newly created bar curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddHiLowBar(string,double[],double[],double[],Color)"/> method.</returns>
+ public HiLowBarItem AddHiLowBar( string label, double[] x, double[] y,
+ double[] baseVal, Color color )
+ {
+ HiLowBarItem curve = new HiLowBarItem( label, x, y, baseVal, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a hi-low bar type curve (<see cref="CurveItem"/> object) to the plot with
+ /// the given data points (<see cref="IPointList"/>) and properties.
+ /// This is simplified way to add curves without knowledge of the
+ /// <see cref="CurveList"/> class. An alternative is to use
+ /// the <see cref="ZedGraph.CurveList" /> Add() method.
+ /// </summary>
+ /// <param name="label">The text label (string) for the curve that will be
+ /// used as a <see cref="Legend"/> entry.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value Trio's that define
+ /// the X, Y, and lower dependent values for this curve</param>
+ /// <param name="color">The color to used to fill the bars</param>
+ /// <returns>A <see cref="HiLowBarItem"/> class for the newly created bar curve.
+ /// This can then be used to access all of the curve properties that
+ /// are not defined as arguments to the
+ /// <see cref="AddHiLowBar(string,IPointList,Color)"/> method.</returns>
+ public HiLowBarItem AddHiLowBar( string label, IPointList points, Color color )
+ {
+ HiLowBarItem curve = new HiLowBarItem( label, points, color );
+ _curveList.Add( curve );
+
+ return curve;
+ }
+
+ /// <summary>
+ /// Add a <see cref="PieItem"/> to the display.
+ /// </summary>
+ /// <param name="value">The value associated with this <see cref="PieItem"/>item.</param>
+ /// <param name="color">The display color for this <see cref="PieItem"/>item.</param>
+ /// <param name="displacement">The amount this <see cref="PieItem"/>item will be
+ /// displaced from the center of the <see cref="PieItem"/>.</param>
+ /// <param name="label">Text label for this <see cref="PieItem"/></param>
+ /// <returns>a reference to the <see cref="PieItem"/> constructed</returns>
+ public PieItem AddPieSlice( double value, Color color, double displacement, string label )
+ {
+ PieItem slice = new PieItem( value, color, displacement, label );
+ this.CurveList.Add( slice );
+ return slice;
+ }
+
+ /// <summary>
+ /// Add a <see cref="PieItem"/> to the display, providing a gradient fill for the pie color.
+ /// </summary>
+ /// <param name="value">The value associated with this <see cref="PieItem"/> instance.</param>
+ /// <param name="color1">The starting display color for the gradient <see cref="Fill"/> for this
+ /// <see cref="PieItem"/> instance.</param>
+ /// <param name="color2">The ending display color for the gradient <see cref="Fill"/> for this
+ /// <see cref="PieItem"/> instance.</param>
+ /// <param name="fillAngle">The angle for the gradient <see cref="Fill"/>.</param>
+ /// <param name="displacement">The amount this <see cref="PieItem"/> instance will be
+ /// displaced from the center point.</param>
+ /// <param name="label">Text label for this <see cref="PieItem"/> instance.</param>
+ public PieItem AddPieSlice( double value, Color color1, Color color2, float fillAngle,
+ double displacement, string label )
+ {
+ PieItem slice = new PieItem( value, color1, color2, fillAngle, displacement, label );
+ this.CurveList.Add( slice );
+ return slice;
+ }
+
+ /// <summary>
+ ///Creates all the <see cref="PieItem"/>s for a single Pie Chart.
+ /// </summary>
+ /// <param name="values">double array containing all <see cref="PieItem.Value"/>s
+ /// for a single PieChart.
+ /// </param>
+ /// <param name="labels"> string array containing all <see cref="CurveItem.Label"/>s
+ /// for a single PieChart.
+ /// </param>
+ /// <returns>an array containing references to all <see cref="PieItem"/>s comprising
+ /// the Pie Chart.</returns>
+ public PieItem[] AddPieSlices( double[] values, string[] labels )
+ {
+ PieItem[] slices = new PieItem[values.Length];
+ for ( int x = 0; x < values.Length; x++ )
+ {
+ slices[x] = new PieItem( values[x], labels[x] );
+ this.CurveList.Add( slices[x] );
+ }
+ return slices;
+ }
+
+ #endregion
+
+ #region General Utility Methods
+ /// <summary>
+ /// Transform a data point from the specified coordinate type
+ /// (<see cref="CoordType"/>) to screen coordinates (pixels).
+ /// </summary>
+ /// <remarks>This method implicitly assumes that <see cref="ZedGraph.Chart.Rect"/>
+ /// has already been calculated via <see cref="AxisChange()"/> or
+ /// <see cref="Draw"/> methods, or the <see cref="ZedGraph.Chart.Rect"/> is
+ /// set manually (see <see cref="ZedGraph.Chart.IsRectAuto"/>).</remarks>
+ /// <param name="ptF">The X,Y pair that defines the point in user
+ /// coordinates.</param>
+ /// <param name="coord">A <see cref="CoordType"/> type that defines the
+ /// coordinate system in which the X,Y pair is defined.</param>
+ /// <returns>A point in screen coordinates that corresponds to the
+ /// specified user point.</returns>
+ public PointF GeneralTransform( PointF ptF, CoordType coord )
+ {
+ // Setup the scaling data based on the chart rect
+ _xAxis.Scale.SetupScaleData( this, _xAxis );
+ foreach ( Axis axis in _yAxisList )
+ axis.Scale.SetupScaleData( this, axis );
+ foreach ( Axis axis in _y2AxisList )
+ axis.Scale.SetupScaleData( this, axis );
+
+ return this.TransformCoord( ptF.X, ptF.Y, coord );
+ }
+
+ /// <summary>
+ /// Transform a data point from the specified coordinate type
+ /// (<see cref="CoordType"/>) to screen coordinates (pixels).
+ /// </summary>
+ /// <remarks>This method implicitly assumes that <see cref="ZedGraph.Chart.Rect"/>
+ /// has already been calculated via <see cref="AxisChange()"/> or
+ /// <see cref="Draw"/> methods, or the <see cref="ZedGraph.Chart.Rect"/> is
+ /// set manually (see <see cref="ZedGraph.Chart.IsRectAuto"/>).
+ /// Note that this method is more accurate than the <see cref="GeneralTransform(PointF,CoordType)" />
+ /// overload, since it uses double types. This would typically only be significant for
+ /// <see cref="AxisType.Date" /> coordinates.
+ /// </remarks>
+ /// <param name="x">The x coordinate that defines the location in user space</param>
+ /// <param name="y">The y coordinate that defines the location in user space</param>
+ /// <param name="coord">A <see cref="CoordType"/> type that defines the
+ /// coordinate system in which the X,Y pair is defined.</param>
+ /// <returns>A point in screen coordinates that corresponds to the
+ /// specified user point.</returns>
+ public PointF GeneralTransform( double x, double y, CoordType coord )
+ {
+ // Setup the scaling data based on the chart rect
+ _xAxis.Scale.SetupScaleData( this, _xAxis );
+ foreach ( Axis axis in _yAxisList )
+ axis.Scale.SetupScaleData( this, axis );
+ foreach ( Axis axis in _y2AxisList )
+ axis.Scale.SetupScaleData( this, axis );
+
+ return this.TransformCoord( x, y, coord );
+ }
+
+ /// <summary>
+ /// Return the user scale values that correspond to the specified screen
+ /// coordinate position (pixels). This overload assumes the default
+ /// <see cref="XAxis" /> and <see cref="YAxis" />.
+ /// </summary>
+ /// <remarks>This method implicitly assumes that <see cref="ZedGraph.Chart.Rect"/>
+ /// has already been calculated via <see cref="AxisChange()"/> or
+ /// <see cref="Draw"/> methods, or the <see cref="ZedGraph.Chart.Rect"/> is
+ /// set manually (see <see cref="ZedGraph.Chart.IsRectAuto"/>).</remarks>
+ /// <param name="ptF">The X,Y pair that defines the screen coordinate
+ /// point of interest</param>
+ /// <param name="x">The resultant value in user coordinates from the
+ /// <see cref="XAxis"/></param>
+ /// <param name="y">The resultant value in user coordinates from the
+ /// primary <see cref="YAxis"/></param>
+ public void ReverseTransform( PointF ptF, out double x, out double y )
+ {
+ // Setup the scaling data based on the chart rect
+ _xAxis.Scale.SetupScaleData( this, _xAxis );
+ this.YAxis.Scale.SetupScaleData( this, this.YAxis );
+
+ x = this.XAxis.Scale.ReverseTransform( ptF.X );
+ y = this.YAxis.Scale.ReverseTransform( ptF.Y );
+ }
+
+ /// <summary>
+ /// Return the user scale values that correspond to the specified screen
+ /// coordinate position (pixels).
+ /// </summary>
+ /// <remarks>This method implicitly assumes that <see cref="ZedGraph.Chart.Rect"/>
+ /// has already been calculated via <see cref="AxisChange()"/> or
+ /// <see cref="Draw"/> methods, or the <see cref="ZedGraph.Chart.Rect"/> is
+ /// set manually (see <see cref="ZedGraph.Chart.IsRectAuto"/>).</remarks>
+ /// <param name="ptF">The X,Y pair that defines the screen coordinate
+ /// point of interest</param>
+ /// <param name="x">The resultant value in user coordinates from the
+ /// <see cref="XAxis"/></param>
+ /// <param name="x2">The resultant value in user coordinates from the
+ /// <see cref="X2Axis"/></param>
+ /// <param name="y">The resultant value in user coordinates from the
+ /// primary <see cref="YAxis"/></param>
+ /// <param name="y2">The resultant value in user coordinates from the
+ /// primary <see cref="Y2Axis"/></param>
+ public void ReverseTransform( PointF ptF, out double x, out double x2, out double y,
+ out double y2 )
+ {
+ // Setup the scaling data based on the chart rect
+ _xAxis.Scale.SetupScaleData( this, _xAxis );
+ _x2Axis.Scale.SetupScaleData( this, _x2Axis );
+ this.YAxis.Scale.SetupScaleData( this, this.YAxis );
+ this.Y2Axis.Scale.SetupScaleData( this, this.Y2Axis );
+
+ x = this.XAxis.Scale.ReverseTransform( ptF.X );
+ x2 = this.X2Axis.Scale.ReverseTransform( ptF.X );
+ y = this.YAxis.Scale.ReverseTransform( ptF.Y );
+ y2 = this.Y2Axis.Scale.ReverseTransform( ptF.Y );
+ }
+
+ /// <summary>
+ /// Return the user scale values that correspond to the specified screen
+ /// coordinate position (pixels).
+ /// </summary>
+ /// <remarks>This method implicitly assumes that <see cref="ZedGraph.Chart.Rect"/>
+ /// has already been calculated via <see cref="AxisChange()"/> or
+ /// <see cref="Draw"/> methods, or the <see cref="ZedGraph.Chart.Rect"/> is
+ /// set manually (see <see cref="ZedGraph.Chart.IsRectAuto"/>).</remarks>
+ /// <param name="ptF">The X,Y pair that defines the screen coordinate
+ /// point of interest</param>
+ /// <param name="isX2Axis">true to return data that corresponds to an
+ /// <see cref="X2Axis" />, false for an <see cref="XAxis" />.</param>
+ /// <param name="isY2Axis">true to return data that corresponds to a
+ /// <see cref="Y2Axis" />, false for a <see cref="YAxis" />.</param>
+ /// <param name="yAxisIndex">The ordinal index of the Y or Y2 axis from which
+ /// to return data (see <seealso cref="YAxisList"/>, <seealso cref="Y2AxisList"/>)
+ /// </param>
+ /// <param name="x">The resultant value in user coordinates from the
+ /// <see cref="XAxis"/></param>
+ /// <param name="y">The resultant value in user coordinates from the
+ /// primary <see cref="YAxis"/></param>
+ public void ReverseTransform( PointF ptF, bool isX2Axis, bool isY2Axis, int yAxisIndex,
+ out double x, out double y )
+ {
+ // Setup the scaling data based on the chart rect
+ Axis xAxis = _xAxis;
+ if ( isX2Axis )
+ xAxis = _x2Axis;
+
+ xAxis.Scale.SetupScaleData( this, xAxis );
+ x = xAxis.Scale.ReverseTransform( ptF.X );
+
+ Axis yAxis = null;
+ if ( isY2Axis && Y2AxisList.Count > yAxisIndex )
+ yAxis = Y2AxisList[yAxisIndex];
+ else if ( !isY2Axis && YAxisList.Count > yAxisIndex )
+ yAxis = YAxisList[yAxisIndex];
+
+ if ( yAxis != null )
+ {
+ yAxis.Scale.SetupScaleData( this, yAxis );
+ y = yAxis.Scale.ReverseTransform( ptF.Y );
+ }
+ else
+ y = PointPair.Missing;
+ }
+
+ /// <summary>
+ /// Return the user scale values that correspond to the specified screen
+ /// coordinate position (pixels) for all y axes.
+ /// </summary>
+ /// <remarks>This method implicitly assumes that <see cref="ZedGraph.Chart.Rect"/>
+ /// has already been calculated via <see cref="AxisChange()"/> or
+ /// <see cref="Draw"/> methods, or the <see cref="ZedGraph.Chart.Rect"/> is
+ /// set manually (see <see cref="ZedGraph.Chart.IsRectAuto"/>).</remarks>
+ /// <param name="ptF">The X,Y pair that defines the screen coordinate
+ /// point of interest</param>
+ /// <param name="x">The resultant value in user coordinates from the
+ /// <see cref="XAxis"/></param>
+ /// <param name="x2">The resultant value in user coordinates from the
+ /// <see cref="X2Axis"/></param>
+ /// <param name="y">An array of resultant values in user coordinates from the
+ /// list of <see cref="YAxis"/> instances. This method allocates the
+ /// array for you, according to the number of <see cref="YAxis" /> objects
+ /// in the list.</param>
+ /// <param name="y2">An array of resultant values in user coordinates from the
+ /// list of <see cref="Y2Axis"/> instances. This method allocates the
+ /// array for you, according to the number of <see cref="Y2Axis" /> objects
+ /// in the list.</param>
+ public void ReverseTransform( PointF ptF, out double x, out double x2, out double[] y,
+ out double[] y2 )
+ {
+ // Setup the scaling data based on the chart rect
+ _xAxis.Scale.SetupScaleData( this, _xAxis );
+ x = this.XAxis.Scale.ReverseTransform( ptF.X );
+ _x2Axis.Scale.SetupScaleData( this, _x2Axis );
+ x2 = this.X2Axis.Scale.ReverseTransform( ptF.X );
+
+ y = new double[_yAxisList.Count];
+ y2 = new double[_y2AxisList.Count];
+
+ for ( int i = 0; i < _yAxisList.Count; i++ )
+ {
+ Axis axis = _yAxisList[i];
+ axis.Scale.SetupScaleData( this, axis );
+ y[i] = axis.Scale.ReverseTransform( ptF.Y );
+ }
+ for ( int i = 0; i < _y2AxisList.Count; i++ )
+ {
+ Axis axis = _y2AxisList[i];
+ axis.Scale.SetupScaleData( this, axis );
+ y2[i] = axis.Scale.ReverseTransform( ptF.Y );
+ }
+ }
+
+ /// <summary>
+ /// Add a secondary <see cref="YAxis" /> (left side) to the list of axes
+ /// in the Graph.
+ /// </summary>
+ /// <remarks>
+ /// Note that the primary <see cref="YAxis" /> is always included by default.
+ /// This method turns off the <see cref="MajorTic" /> and <see cref="MinorTic" />
+ /// <see cref="MinorTic.IsOpposite" /> and <see cref="MinorTic.IsInside" />
+ /// properties by default.
+ /// </remarks>
+ /// <param name="title">The title for the <see cref="YAxis" />.</param>
+ /// <returns>the ordinal position (index) in the <see cref="YAxisList" />.</returns>
+ public int AddYAxis( string title )
+ {
+ YAxis axis = new YAxis( title );
+ axis.MajorTic.IsOpposite = false;
+ axis.MinorTic.IsOpposite = false;
+ axis.MajorTic.IsInside = false;
+ axis.MinorTic.IsInside = false;
+ _yAxisList.Add( axis );
+ return _yAxisList.Count - 1;
+ }
+
+ /// <summary>
+ /// Add a secondary <see cref="Y2Axis" /> (right side) to the list of axes
+ /// in the Graph.
+ /// </summary>
+ /// <remarks>
+ /// Note that the primary <see cref="Y2Axis" /> is always included by default.
+ /// This method turns off the <see cref="MajorTic" /> and <see cref="MinorTic" />
+ /// <see cref="MinorTic.IsOpposite" /> and <see cref="MinorTic.IsInside" />
+ /// properties by default.
+ /// </remarks>
+ /// <param name="title">The title for the <see cref="Y2Axis" />.</param>
+ /// <returns>the ordinal position (index) in the <see cref="Y2AxisList" />.</returns>
+ public int AddY2Axis( string title )
+ {
+ Y2Axis axis = new Y2Axis( title );
+ axis.MajorTic.IsOpposite = false;
+ axis.MinorTic.IsOpposite = false;
+ axis.MajorTic.IsInside = false;
+ axis.MinorTic.IsInside = false;
+ _y2AxisList.Add( axis );
+ return _y2AxisList.Count - 1;
+ }
+
+ /// <summary>
+ /// Find the object that lies closest to the specified mouse (screen) point.
+ /// </summary>
+ /// <remarks>
+ /// This method will search through all of the graph objects, such as
+ /// <see cref="Axis"/>, <see cref="Legend"/>, <see cref="PaneBase.Title"/>,
+ /// <see cref="GraphObj"/>, and <see cref="CurveItem"/>.
+ /// If the mouse point is within the bounding box of the items (or in the case
+ /// of <see cref="ArrowObj"/> and <see cref="CurveItem"/>, within
+ /// <see cref="Default.NearestTol"/> pixels), then the object will be returned.
+ /// You must check the type of the object to determine what object was
+ /// selected (for example, "if ( object is Legend ) ..."). The
+ /// <see paramref="index"/> parameter returns the index number of the item
+ /// within the selected object (such as the point number within a
+ /// <see cref="CurveItem"/> object.
+ /// </remarks>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="nearestObj">A reference to the nearest object to the
+ /// specified screen point. This can be any of <see cref="Axis"/>,
+ /// <see cref="Legend"/>, <see cref="PaneBase.Title"/>,
+ /// <see cref="TextObj"/>, <see cref="ArrowObj"/>, or <see cref="CurveItem"/>.
+ /// Note: If the pane title is selected, then the <see cref="GraphPane"/> object
+ /// will be returned.
+ /// </param>
+ /// <param name="index">The index number of the item within the selected object
+ /// (where applicable). For example, for a <see cref="CurveItem"/> object,
+ /// <see paramref="index"/> will be the index number of the nearest data point,
+ /// accessible via <see cref="CurveItem.Points">CurveItem.Points[index]</see>.
+ /// index will be -1 if no data points are available.</param>
+ /// <returns>true if an object was found, false otherwise.</returns>
+ /// <seealso cref="FindNearestObject"/>
+ public bool FindNearestObject( PointF mousePt, Graphics g,
+ out object nearestObj, out int index )
+ {
+ nearestObj = null;
+ index = -1;
+
+ // Make sure that the axes & data are being drawn
+ if ( AxisRangesValid() )
+ {
+ float scaleFactor = CalcScaleFactor();
+ //int hStack;
+ //float legendWidth, legendHeight;
+ RectangleF tmpRect;
+ GraphObj saveGraphItem = null;
+ int saveIndex = -1;
+ ZOrder saveZOrder = ZOrder.H_BehindAll;
+
+ // Calculate the chart rect, deducting the area for the scales, titles, legend, etc.
+ RectangleF tmpChartRect = CalcChartRect( g, scaleFactor );
+
+ // See if the point is in a GraphObj
+ // If so, just save the object and index so we can see if other overlying objects were
+ // intersected as well.
+ if ( this.GraphObjList.FindPoint( mousePt, this, g, scaleFactor, out index ) )
+ {
+ saveGraphItem = this.GraphObjList[index];
+ saveIndex = index;
+ saveZOrder = saveGraphItem.ZOrder;
+ }
+
+ // See if the point is in the legend
+ if ( saveZOrder <= ZOrder.B_BehindLegend &&
+ this.Legend.FindPoint( mousePt, this, scaleFactor, out index ) )
+ {
+ nearestObj = this.Legend;
+ return true;
+ }
+
+ // See if the point is in the Pane Title
+ SizeF paneTitleBox = _title._fontSpec.BoundingBox( g, _title._text, scaleFactor );
+ if ( saveZOrder <= ZOrder.H_BehindAll && _title._isVisible )
+ {
+ tmpRect = new RectangleF( ( _rect.Left + _rect.Right - paneTitleBox.Width ) / 2,
+ _rect.Top + _margin.Top * scaleFactor,
+ paneTitleBox.Width, paneTitleBox.Height );
+ if ( tmpRect.Contains( mousePt ) )
+ {
+ nearestObj = this;
+ return true;
+ }
+ }
+
+ float left = tmpChartRect.Left;
+
+ // See if the point is in one of the Y Axes
+ for ( int yIndex = 0; yIndex < _yAxisList.Count; yIndex++ )
+ {
+ Axis yAxis = _yAxisList[yIndex];
+ float width = yAxis._tmpSpace;
+ if ( width > 0 )
+ {
+ tmpRect = new RectangleF( left - width, tmpChartRect.Top,
+ width, tmpChartRect.Height );
+ if ( saveZOrder <= ZOrder.D_BehindAxis && tmpRect.Contains( mousePt ) )
+ {
+ nearestObj = yAxis;
+ index = yIndex;
+ return true;
+ }
+
+ left -= width;
+ }
+ }
+
+ left = tmpChartRect.Right;
+
+ // See if the point is in one of the Y2 Axes
+ for ( int yIndex = 0; yIndex < _y2AxisList.Count; yIndex++ )
+ {
+ Axis y2Axis = _y2AxisList[yIndex];
+ float width = y2Axis._tmpSpace;
+ if ( width > 0 )
+ {
+ tmpRect = new RectangleF( left, tmpChartRect.Top,
+ width, tmpChartRect.Height );
+ if ( saveZOrder <= ZOrder.D_BehindAxis && tmpRect.Contains( mousePt ) )
+ {
+ nearestObj = y2Axis;
+ index = yIndex;
+ return true;
+ }
+
+ left += width;
+ }
+ }
+
+ // See if the point is in the X Axis
+ float height = _xAxis._tmpSpace;
+
+ tmpRect = new RectangleF( tmpChartRect.Left, tmpChartRect.Bottom,
+ tmpChartRect.Width, height ); //_rect.Bottom - tmpChartRect.Bottom );
+
+ if ( saveZOrder <= ZOrder.D_BehindAxis && tmpRect.Contains( mousePt ) )
+ {
+ nearestObj = this.XAxis;
+ return true;
+ }
+
+ // See if the point is in the X2 Axis
+ height = _x2Axis._tmpSpace;
+
+ tmpRect = new RectangleF( tmpChartRect.Left,
+ tmpChartRect.Top - height,
+ tmpChartRect.Width,
+ height );
+ if ( saveZOrder <= ZOrder.D_BehindAxis && tmpRect.Contains( mousePt ) )
+ {
+ nearestObj = this.X2Axis;
+ return true;
+ }
+
+ CurveItem curve;
+ // See if it's a data point
+ if ( saveZOrder <= ZOrder.E_BehindCurves && FindNearestPoint( mousePt, out curve, out index ) )
+ {
+ nearestObj = curve;
+ return true;
+ }
+
+ if ( saveGraphItem != null )
+ {
+ index = saveIndex;
+ nearestObj = saveGraphItem;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Find the data point that lies closest to the specified mouse (screen)
+ /// point for the specified curve.
+ /// </summary>
+ /// <remarks>
+ /// This method will search only through the points for the specified
+ /// curve to determine which point is
+ /// nearest the mouse point. It will only consider points that are within
+ /// <see cref="Default.NearestTol"/> pixels of the screen point.
+ /// </remarks>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="nearestCurve">A reference to the <see cref="CurveItem"/>
+ /// instance that contains the closest point. nearestCurve will be null if
+ /// no data points are available.</param>
+ /// <param name="targetCurve">A <see cref="CurveItem"/> object containing
+ /// the data points to be searched.</param>
+ /// <param name="iNearest">The index number of the closest point. The
+ /// actual data vpoint will then be <see cref="CurveItem.Points">CurveItem.Points[iNearest]</see>
+ /// . iNearest will
+ /// be -1 if no data points are available.</param>
+ /// <returns>true if a point was found and that point lies within
+ /// <see cref="Default.NearestTol"/> pixels
+ /// of the screen point, false otherwise.</returns>
+ public bool FindNearestPoint( PointF mousePt, CurveItem targetCurve,
+ out CurveItem nearestCurve, out int iNearest )
+ {
+ CurveList targetCurveList = new CurveList();
+ targetCurveList.Add( targetCurve );
+ return FindNearestPoint( mousePt, targetCurveList,
+ out nearestCurve, out iNearest );
+ }
+
+ /// <summary>
+ /// Find the data point that lies closest to the specified mouse (screen)
+ /// point.
+ /// </summary>
+ /// <remarks>
+ /// This method will search through all curves in
+ /// <see cref="GraphPane.CurveList"/> to find which point is
+ /// nearest. It will only consider points that are within
+ /// <see cref="Default.NearestTol"/> pixels of the screen point.
+ /// </remarks>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="nearestCurve">A reference to the <see cref="CurveItem"/>
+ /// instance that contains the closest point. nearestCurve will be null if
+ /// no data points are available.</param>
+ /// <param name="iNearest">The index number of the closest point. The
+ /// actual data vpoint will then be <see cref="CurveItem.Points">CurveItem.Points[iNearest]</see>
+ /// . iNearest will
+ /// be -1 if no data points are available.</param>
+ /// <returns>true if a point was found and that point lies within
+ /// <see cref="Default.NearestTol"/> pixels
+ /// of the screen point, false otherwise.</returns>
+ public bool FindNearestPoint( PointF mousePt,
+ out CurveItem nearestCurve, out int iNearest )
+ {
+ return FindNearestPoint( mousePt, _curveList,
+ out nearestCurve, out iNearest );
+ }
+
+ /// <summary>
+ /// Find the data point that lies closest to the specified mouse (screen)
+ /// point.
+ /// </summary>
+ /// <remarks>
+ /// This method will search through the specified list of curves to find which point is
+ /// nearest. It will only consider points that are within
+ /// <see cref="Default.NearestTol"/> pixels of the screen point, and it will
+ /// only consider <see cref="CurveItem"/>'s that are in
+ /// <paramref name="targetCurveList"/>.
+ /// </remarks>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="targetCurveList">A <see cref="CurveList"/> object containing
+ /// a subset of <see cref="CurveItem"/>'s to be searched.</param>
+ /// <param name="nearestCurve">A reference to the <see cref="CurveItem"/>
+ /// instance that contains the closest point. nearestCurve will be null if
+ /// no data points are available.</param>
+ /// <param name="iNearest">The index number of the closest point. The
+ /// actual data vpoint will then be <see cref="CurveItem.Points">CurveItem.Points[iNearest]</see>
+ /// . iNearest will
+ /// be -1 if no data points are available.</param>
+ /// <returns>true if a point was found and that point lies within
+ /// <see cref="Default.NearestTol"/> pixels
+ /// of the screen point, false otherwise.</returns>
+ public bool FindNearestPoint( PointF mousePt, CurveList targetCurveList,
+ out CurveItem nearestCurve, out int iNearest )
+ {
+ CurveItem nearestBar = null;
+ int iNearestBar = -1;
+ nearestCurve = null;
+ iNearest = -1;
+
+ // If the point is outside the ChartRect, always return false
+ if ( !_chart._rect.Contains( mousePt ) )
+ return false;
+
+ double x, x2;
+ double[] y;
+ double[] y2;
+
+ //ReverseTransform( mousePt, out x, out y, out y2 );
+ ReverseTransform( mousePt, out x, out x2, out y, out y2 );
+
+ if ( !AxisRangesValid() )
+ return false;
+
+ ValueHandler valueHandler = new ValueHandler( this, false );
+
+ //double yPixPerUnit = chartRect.Height / ( yAxis.Max - yAxis.Min );
+ //double y2PixPerUnit; // = chartRect.Height / ( y2Axis.Max - y2Axis.Min );
+
+ double yPixPerUnitAct, yAct, yMinAct, yMaxAct, xAct;
+ double minDist = 1e20;
+ double xVal, yVal, dist = 99999, distX, distY;
+ double tolSquared = Default.NearestTol * Default.NearestTol;
+
+ int iBar = 0;
+
+ foreach ( CurveItem curve in targetCurveList )
+ {
+ //test for pie first...if it's a pie rest of method superfluous
+ if ( curve is PieItem && curve.IsVisible )
+ {
+ if ( ( (PieItem)curve ).SlicePath != null &&
+ ( (PieItem)curve ).SlicePath.IsVisible( mousePt ) )
+ {
+ nearestBar = curve;
+ iNearestBar = 0;
+ }
+
+ continue;
+ }
+ else if ( curve.IsVisible )
+ {
+ int yIndex = curve.GetYAxisIndex( this );
+ Axis yAxis = curve.GetYAxis( this );
+ Axis xAxis = curve.GetXAxis( this );
+
+ if ( curve.IsY2Axis )
+ {
+ yAct = y2[yIndex];
+ yMinAct = _y2AxisList[yIndex]._scale._min;
+ yMaxAct = _y2AxisList[yIndex]._scale._max;
+ }
+ else
+ {
+ yAct = y[yIndex];
+ yMinAct = _yAxisList[yIndex]._scale._min;
+ yMaxAct = _yAxisList[yIndex]._scale._max;
+ }
+
+ yPixPerUnitAct = _chart._rect.Height / ( yMaxAct - yMinAct );
+
+ double xPixPerUnit = _chart._rect.Width / ( xAxis._scale._max - xAxis._scale._min );
+ xAct = xAxis is XAxis ? x : x2;
+
+ IPointList points = curve.Points;
+ float barWidth = curve.GetBarWidth( this );
+ double barWidthUserHalf;
+ Axis baseAxis = curve.BaseAxis( this );
+ bool isXBaseAxis = ( baseAxis is XAxis || baseAxis is X2Axis );
+ if ( isXBaseAxis )
+ barWidthUserHalf = barWidth / xPixPerUnit / 2.0;
+ else
+ barWidthUserHalf = barWidth / yPixPerUnitAct / 2.0;
+
+ if ( points != null )
+ {
+ for ( int iPt = 0; iPt < curve.NPts; iPt++ )
+ {
+ // xVal is the user scale X value of the current point
+ if ( xAxis._scale.IsAnyOrdinal && !curve.IsOverrideOrdinal )
+ xVal = (double)iPt + 1.0;
+ else
+ xVal = points[iPt].X;
+
+ // yVal is the user scale Y value of the current point
+ if ( yAxis._scale.IsAnyOrdinal && !curve.IsOverrideOrdinal )
+ yVal = (double)iPt + 1.0;
+ else
+ yVal = points[iPt].Y;
+
+ if ( xVal != PointPair.Missing &&
+ yVal != PointPair.Missing )
+ {
+
+ if ( curve.IsBar || curve is ErrorBarItem ||
+ curve is HiLowBarItem || curve is OHLCBarItem ||
+ curve is JapaneseCandleStickItem )
+ {
+ double baseVal, lowVal, hiVal;
+ valueHandler.GetValues( curve, iPt, out baseVal,
+ out lowVal, out hiVal );
+
+ if ( lowVal > hiVal )
+ {
+ double tmpVal = lowVal;
+ lowVal = hiVal;
+ hiVal = tmpVal;
+ }
+
+ if ( isXBaseAxis )
+ {
+
+ double centerVal = valueHandler.BarCenterValue( curve, barWidth, iPt, xVal, iBar );
+
+ if ( xAct < centerVal - barWidthUserHalf ||
+ xAct > centerVal + barWidthUserHalf ||
+ yAct < lowVal || yAct > hiVal )
+ continue;
+ }
+ else
+ {
+ double centerVal = valueHandler.BarCenterValue( curve, barWidth, iPt, yVal, iBar );
+
+ if ( yAct < centerVal - barWidthUserHalf ||
+ yAct > centerVal + barWidthUserHalf ||
+ xAct < lowVal || xAct > hiVal )
+ continue;
+ }
+
+ if ( nearestBar == null )
+ {
+ iNearestBar = iPt;
+ nearestBar = curve;
+ }
+ }
+ else if ( xVal >= xAxis._scale._min && xVal <= xAxis._scale._max &&
+ yVal >= yMinAct && yVal <= yMaxAct )
+ {
+ if ( curve is LineItem && _lineType == LineType.Stack )
+ {
+ double zVal;
+ valueHandler.GetValues( curve, iPt, out xVal, out zVal, out yVal );
+ }
+
+ distX = ( xVal - xAct ) * xPixPerUnit;
+ distY = ( yVal - yAct ) * yPixPerUnitAct;
+ dist = distX * distX + distY * distY;
+
+ if ( dist >= minDist )
+ continue;
+
+ minDist = dist;
+ iNearest = iPt;
+ nearestCurve = curve;
+ }
+
+ }
+ }
+
+ if ( curve.IsBar )
+ iBar++;
+ }
+ }
+ }
+
+ if ( nearestCurve is LineItem )
+ {
+ float halfSymbol = (float)( ( (LineItem)nearestCurve ).Symbol.Size *
+ CalcScaleFactor() / 2 );
+ minDist -= halfSymbol * halfSymbol;
+ if ( minDist < 0 )
+ minDist = 0;
+ }
+
+ if ( minDist >= tolSquared && nearestBar != null )
+ {
+ // if no point met the tolerance, but a bar was found, use it
+ nearestCurve = nearestBar;
+ iNearest = iNearestBar;
+ return true;
+ }
+ else if ( minDist < tolSquared )
+ {
+ // Did we find a close point, and is it within the tolerance?
+ // (minDist is the square of the distance in pixel units)
+ return true;
+ }
+ else // otherwise, no valid point found
+ return false;
+ }
+
+ /// <summary>
+ /// Search through the <see cref="GraphObjList" /> and <see cref="CurveList" /> for
+ /// items that contain active <see cref="Link" /> objects.
+ /// </summary>
+ /// <param name="mousePt">The mouse location where the click occurred</param>
+ /// <param name="g">An appropriate <see cref="Graphics" /> instance</param>
+ /// <param name="scaleFactor">The current scaling factor for drawing operations.</param>
+ /// <param name="source">The clickable object that was found. Typically a type of
+ /// <see cref="GraphObj" /> or a type of <see cref="CurveItem" />.</param>
+ /// <param name="link">The <see cref="Link" /> instance that is contained within
+ /// the <see paramref="source" /> object.</param>
+ /// <param name="index">An index value, indicating which point was clicked for
+ /// <see cref="CurveItem" /> type objects.</param>
+ /// <returns>returns true if a clickable link was found under the
+ /// <see paramref="mousePt" />, or false otherwise.
+ /// </returns>
+ public bool FindLinkableObject( PointF mousePt, Graphics g, float scaleFactor,
+ out object source, out Link link, out int index )
+ {
+ index = -1;
+
+ // First look for graph objects that lie in front of the data points
+ foreach ( GraphObj graphObj in _graphObjList )
+ {
+ link = graphObj._link;
+ bool inFront = graphObj.IsInFrontOfData;
+
+ if ( link.IsActive )
+ {
+ if ( graphObj.PointInBox( mousePt, this, g, scaleFactor ) )
+ {
+ source = graphObj;
+ return true;
+ }
+ }
+ }
+
+ // Second, look at the curve data points
+ foreach ( CurveItem curve in _curveList )
+ {
+ link = curve._link;
+
+ if ( link.IsActive )
+ {
+ CurveItem nearestCurve;
+
+ if ( FindNearestPoint( mousePt, curve, out nearestCurve, out index ) )
+ {
+ source = curve;
+ return true;
+ }
+ }
+ }
+
+ // Third, look for graph objects that lie behind the data points
+ foreach ( GraphObj graphObj in _graphObjList )
+ {
+ link = graphObj._link;
+ bool inFront = graphObj.IsInFrontOfData;
+
+ if ( link.IsActive )
+ {
+ if ( graphObj.PointInBox( mousePt, this, g, scaleFactor ) )
+ {
+ source = graphObj;
+ return true;
+ }
+ }
+ }
+
+ source = null;
+ link = null;
+ index = -1;
+ return false;
+
+ }
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Find any objects that exist within the specified (screen) rectangle.
+ /// This method will search through all of the graph objects, such as
+ /// <see cref="Axis"/>, <see cref="Legend"/>, <see cref="PaneBase.Title"/>,
+ /// <see cref="GraphObj"/>, and <see cref="CurveItem"/>.
+ /// and see if the objects' bounding boxes are within the specified (screen) rectangle
+ /// This method returns true if any are found.
+ /// </summary>
+ public bool FindContainedObjects( RectangleF rectF, Graphics g,
+ out CurveList containedObjs )
+ {
+ containedObjs = new CurveList();
+
+ foreach ( CurveItem ci in this.CurveList )
+ {
+ for ( int i = 0; i < ci.Points.Count; i++ )
+ {
+ if ( ci.Points[i].X > rectF.Left &&
+ ci.Points[i].X < rectF.Right &&
+ ci.Points[i].Y > rectF.Bottom &&
+ ci.Points[i].Y < rectF.Top )
+ {
+ containedObjs.Add( ci );
+ }
+ }
+ }
+ return ( containedObjs.Count > 0 );
+ }
+
+ #endregion
+
+ }
+}
+
diff --git a/ZedGraph/HSBColor.cs b/ZedGraph/HSBColor.cs
new file mode 100644
index 0000000..8d6d15f
--- /dev/null
+++ b/ZedGraph/HSBColor.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Hue-Saturation-Brightness Color class to store a color value, and to manage conversions
+ /// to and from RGB colors in the <see cref="Color" /> struct.
+ /// </summary>
+ /// <remarks>
+ /// This class is based on code from http://www.cs.rit.edu/~ncs/color/ by Eugene Vishnevsky.
+ /// This struct stores the hue, saturation, brightness, and alpha values internally as
+ /// <see cref="byte" /> values from 0 to 255. The hue represents a fraction of the 360 degrees
+ /// of color space available. The saturation is the color intensity, where 0 represents gray scale
+ /// and 255 is the most colored. For the brightness, 0 represents black and 255
+ /// represents white.
+ /// </remarks>
+ [Serializable]
+ public struct HSBColor
+ {
+ /// <summary>
+ /// The color hue value, ranging from 0 to 255.
+ /// </summary>
+ /// <remarks>
+ /// This property is actually a rescaling of the 360 degrees on the color wheel to 255
+ /// possible values. Therefore, every 42.5 units is a new sector, with the following
+ /// convention: red=0, yellow=42.5, green=85, cyan=127.5, blue=170, magenta=212.5
+ /// </remarks>
+ public byte H;
+ /// <summary>
+ /// The color saturation (intensity) value, ranging from 0 (gray scale) to 255 (most colored).
+ /// </summary>
+ public byte S;
+ /// <summary>
+ /// The brightness value, ranging from 0 (black) to 255 (white).
+ /// </summary>
+ public byte B;
+ /// <summary>
+ /// The alpha value (opacity), ranging from 0 (transparent) to 255 (opaque).
+ /// </summary>
+ public byte A;
+
+ /// <summary>
+ /// Constructor to load an <see cref="HSBColor" /> struct from hue, saturation and
+ /// brightness values
+ /// </summary>
+ /// <param name="h">The color hue value, ranging from 0 to 255</param>
+ /// <param name="s">The color saturation (intensity) value, ranging from 0 (gray scale)
+ /// to 255 (most colored)</param>
+ /// <param name="b">The brightness value, ranging from 0 (black) to 255 (white)</param>
+ public HSBColor( int h, int s, int b )
+ {
+ this.H = (byte)h;
+ this.S = (byte)s;
+ this.B = (byte)b;
+ this.A = 255;
+ }
+
+ /// <summary>
+ /// Constructor to load an <see cref="HSBColor" /> struct from hue, saturation,
+ /// brightness, and alpha values
+ /// </summary>
+ /// <param name="h">The color hue value, ranging from 0 to 255</param>
+ /// <param name="s">The color saturation (intensity) value, ranging from 0 (gray scale)
+ /// to 255 (most colored)</param>
+ /// <param name="b">The brightness value, ranging from 0 (black) to 255 (white)</param>
+ /// <param name="a">The alpha value (opacity), ranging from 0 (transparent) to
+ /// 255 (opaque)</param>
+ public HSBColor( int a, int h, int s, int b )
+ : this( h, s, b )
+ {
+ this.A = (byte)a;
+ }
+
+ /// <summary>
+ /// Constructor to load an <see cref="HSBColor" /> struct from a system
+ /// <see cref="Color" /> struct.
+ /// </summary>
+ /// <param name="color">An rgb <see cref="Color" /> struct containing the equivalent
+ /// color you want to generate</param>
+ public HSBColor( Color color )
+ {
+ this = FromRGB( color );
+ }
+
+
+ /// <summary>
+ /// Implicit conversion operator to convert directly from an <see cref="HSBColor" /> to
+ /// a <see cref="Color" /> struct.
+ /// </summary>
+ /// <param name="hsbColor">The <see cref="HSBColor" /> struct to be converted</param>
+ /// <returns>An equivalent <see cref="Color" /> struct that can be used in the GDI+
+ /// graphics library</returns>
+ public static implicit operator Color( HSBColor hsbColor )
+ {
+ return ToRGB( hsbColor );
+ }
+
+ /// <summary>
+ /// Convert an <see cref="HSBColor" /> value to an equivalent <see cref="Color" /> value.
+ /// </summary>
+ /// <remarks>
+ /// This method is based on code from http://www.cs.rit.edu/~ncs/color/ by Eugene Vishnevsky.
+ /// </remarks>
+ /// <param name="hsbColor">The <see cref="HSBColor" /> struct to be converted</param>
+ /// <returns>An equivalent <see cref="Color" /> struct, compatible with the GDI+ library</returns>
+ public static Color ToRGB( HSBColor hsbColor )
+ {
+ Color rgbColor = Color.Black;
+
+ // Determine which sector of the color wheel contains this hue
+ // hsbColor.H ranges from 0 to 255, and there are 6 sectors, so 42.5 per sector
+ int sector = (int) Math.Floor( (double) hsbColor.H / 42.5 );
+ // Calculate where the hue lies within the sector for interpolation purpose
+ double fraction = (double) hsbColor.H / 42.5 - (double) sector;
+
+ double sFrac = (double) hsbColor.S / 255.0;
+ byte p = (byte) (( (double) hsbColor.B * ( 1.0 - sFrac ) ) + 0.5);
+ byte q = (byte) (( (double) hsbColor.B * ( 1.0 - sFrac * fraction ) ) + 0.5);
+ byte t = (byte) (( (double) hsbColor.B * ( 1.0 - sFrac * ( 1.0 - fraction ) ) ) + 0.5);
+
+
+ switch( sector )
+ {
+ case 0: // red - yellow
+ rgbColor = Color.FromArgb( hsbColor.A, hsbColor.B, t, p );
+ break;
+ case 1: // yellow - green
+ rgbColor = Color.FromArgb( hsbColor.A, q, hsbColor.B, p );
+ break;
+ case 2: // green - cyan
+ rgbColor = Color.FromArgb( hsbColor.A, p, hsbColor.B, t );
+ break;
+ case 3: // cyan - blue
+ rgbColor = Color.FromArgb( hsbColor.A, p, q, hsbColor.B );
+ break;
+ case 4: // blue - magenta
+ rgbColor = Color.FromArgb( hsbColor.A, t, p, hsbColor.B );
+ break;
+ case 5:
+ default: // magenta - red
+ rgbColor = Color.FromArgb( hsbColor.A, hsbColor.B, p, q );
+ break;
+ }
+
+ return rgbColor;
+ }
+
+ /// <summary>
+ /// Convert this <see cref="HSBColor" /> value to an equivalent <see cref="Color" /> value.
+ /// </summary>
+ /// <remarks>
+ /// This method is based on code from http://www.cs.rit.edu/~ncs/color/ by Eugene Vishnevsky.
+ /// </remarks>
+ /// <returns>An equivalent <see cref="Color" /> struct, compatible with the GDI+ library</returns>
+ public Color ToRGB()
+ {
+ return ToRGB( this );
+ }
+
+ /// <summary>
+ /// Convert a <see cref="Color" /> value to an equivalent <see cref="HSBColor" /> value.
+ /// </summary>
+ /// <remarks>
+ /// This method is based on code from http://www.cs.rit.edu/~ncs/color/ by Eugene Vishnevsky.
+ /// </remarks>
+ /// <returns>An equivalent <see cref="HSBColor" /> struct</returns>
+ public HSBColor FromRGB()
+ {
+ return FromRGB( this );
+ }
+
+ /// <summary>
+ /// Convert a <see cref="Color" /> value to an equivalent <see cref="HSBColor" /> value.
+ /// </summary>
+ /// <remarks>
+ /// This method is based on code from http://www.cs.rit.edu/~ncs/color/ by Eugene Vishnevsky.
+ /// </remarks>
+ /// <param name="rgbColor">The <see cref="Color" /> struct to be converted</param>
+ /// <returns>An equivalent <see cref="HSBColor" /> struct</returns>
+ public static HSBColor FromRGB( Color rgbColor )
+ {
+ double r = (double) rgbColor.R / 255.0;
+ double g = (double) rgbColor.G / 255.0;
+ double b = (double) rgbColor.B / 255.0;
+
+ double min = Math.Min( Math.Min( r, g ), b );
+ double max = Math.Max( Math.Max( r, g ), b );
+
+ HSBColor hsbColor = new HSBColor( rgbColor.A, 0, 0, 0 );
+
+ hsbColor.B = (byte) ( max * 255.0 + 0.5 );
+
+ double delta = max - min;
+
+ if ( max != 0.0 )
+ {
+ hsbColor.S = (byte) ( delta / max * 255.0 + 0.5 );
+ }
+ else
+ {
+ hsbColor.S = 0;
+ hsbColor.H = 0;
+ return hsbColor;
+ }
+
+ double h;
+ if ( r == max )
+ h = ( g - b ) / delta; // between yellow & magenta
+ else if ( g == max )
+ h = 2 + ( b - r ) / delta; // between cyan & yellow
+ else
+ h = 4 + ( r - g ) / delta; // between magenta & cyan
+
+ hsbColor.H = (byte) ( h * 42.5 );
+ if ( hsbColor.H < 0 )
+ hsbColor.H += 255;
+
+ return hsbColor;
+ }
+
+ }
+}
diff --git a/ZedGraph/HiLowBar.cs b/ZedGraph/HiLowBar.cs
new file mode 100644
index 0000000..407312b
--- /dev/null
+++ b/ZedGraph/HiLowBar.cs
@@ -0,0 +1,377 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This class handles the drawing of the curve <see cref="HiLowBar"/> objects.
+ /// The Hi-Low Bars are the "floating" bars that have a lower and upper value and
+ /// appear at each defined point.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.18 $ $Date: 2007-10-26 08:19:49 $ </version>
+ [Serializable]
+ public class HiLowBar : Bar, ICloneable, ISerializable
+ {
+
+ #region Fields
+ /// <summary>
+ /// Private field that stores the size (width) of this
+ /// <see cref="HiLowBar"/> in points (1/72 inch). Use the public
+ /// property <see cref="Size"/> to access this value.
+ /// </summary>
+ private float _size;
+
+ /// <summary>
+ /// Private field that determines whether the bar width will be based on
+ /// the <see cref="Size"/> value, or it will be based on available
+ /// space similar to <see cref="BarItem"/> objects. Use the public property
+ /// <see cref="IsAutoSize"/> to access this value.
+ /// </summary>
+ private bool _isAutoSize;
+
+ /// <summary>
+ /// The result of the autosize calculation, which is the size of the bars in
+ /// user scale units. This is converted to pixels at draw time.
+ /// </summary>
+ internal double _userScaleSize = 1.0;
+
+ #endregion
+
+ #region Default
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ZedGraph.HiLowBar"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ // Default HiLowBar properties
+ /// <summary>
+ /// The default size (width) for the bars (<see cref="HiLowBar.Size"/> property),
+ /// in units of points.
+ /// </summary>
+ public static float Size = 7;
+
+ /// <summary>
+ /// Default value for the <see cref="HiLowBar.IsAutoSize" /> property.
+ /// </summary>
+ public static bool IsAutoSize = true;
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default constructor that sets all <see cref="HiLowBar"/> properties to default
+ /// values as defined in the <see cref="Bar.Default"/> class.
+ /// </summary>
+ public HiLowBar() : this( Color.Empty )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets the
+ /// <see cref="Color"/> as specified, and the remaining
+ /// <see cref="HiLowBar"/> properties to default
+ /// values as defined in the <see cref="Bar.Default"/> class.
+ /// The specified color is only applied to the
+ /// <see cref="ZedGraph.Fill.Color"/>, and the <see cref="ZedGraph.LineBase.Color"/>
+ /// will be defaulted.
+ /// </summary>
+ /// <param name="color">A <see cref="Color"/> value indicating
+ /// the <see cref="ZedGraph.Fill.Color"/>
+ /// of the Bar.
+ /// </param>
+ public HiLowBar( Color color ) : this( color, Default.Size )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets the
+ /// <see cref="Color"/> and <see cref="Size"/> as specified, and the remaining
+ /// <see cref="HiLowBar"/> properties to default
+ /// values as defined in the <see cref="Bar.Default"/> class.
+ /// The specified color is only applied to the
+ /// <see cref="ZedGraph.Fill.Color"/>, and the <see cref="ZedGraph.LineBase.Color"/>
+ /// will be defaulted.
+ /// </summary>
+ /// <param name="color">A <see cref="Color"/> value indicating
+ /// the <see cref="ZedGraph.Fill.Color"/>
+ /// of the Bar.
+ /// </param>
+ /// <param name="size">The size (width) of the <see cref="HiLowBar"/>'s, in points
+ /// (1/72nd inch)</param>
+ public HiLowBar( Color color, float size ) : base( color )
+ {
+ _size = size;
+ _isAutoSize = Default.IsAutoSize;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="HiLowBar"/> object from which to copy</param>
+ public HiLowBar( HiLowBar rhs ) : base( rhs )
+ {
+ _size = rhs._size;
+ _isAutoSize = rhs._isAutoSize;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ new public HiLowBar Clone()
+ {
+ return new HiLowBar( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected HiLowBar( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _size = info.GetSingle( "size" );
+ _isAutoSize = info.GetBoolean( "isAutoSize" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "size", _size );
+ info.AddValue( "isAutoSize", _isAutoSize );
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets or sets the size of the <see cref="HiLowBar"/>
+ /// </summary>
+ /// <remarks>The size of the bars can be set by this value, which
+ /// is then scaled according to the scaleFactor (see
+ /// <see cref="PaneBase.CalcScaleFactor"/>). Alternatively,
+ /// if <see cref="IsAutoSize"/> is true, the bar width will
+ /// be set according to the maximum available cluster width less
+ /// the cluster gap (see <see cref="BarSettings.GetClusterWidth"/>
+ /// and <see cref="BarSettings.MinClusterGap"/>). That is, if
+ /// <see cref="IsAutoSize"/> is true, then the value of
+ /// <see cref="Size"/> will be ignored. If you modify the value of Size,
+ /// then <see cref="IsAutoSize" /> will be automatically set to false.
+ /// </remarks>
+ /// <value>Size in points (1/72 inch)</value>
+ /// <seealso cref="Default.Size"/>
+ public float Size
+ {
+ get { return _size; }
+ set { _size = value; _isAutoSize = false; }
+ }
+
+ /// <summary>
+ /// Determines whether the bar width will be based on
+ /// the <see cref="Size"/> value, or it will be based on available
+ /// space similar to <see cref="BarItem"/> objects.
+ /// </summary>
+ /// <remarks>If true, then the value of <see cref="Size"/> is ignored.
+ /// If this value is true, then <see cref="BarSettings.MinClusterGap"/> will be used to
+ /// determine the total space between each bar. If the base axis is non-ordinal, then
+ /// <see cref="BarSettings.ClusterScaleWidth" /> will be active. In this case, you may
+ /// want to make sure that <see cref="BarSettings.ClusterScaleWidthAuto" /> is true.
+ /// </remarks>
+ public bool IsAutoSize
+ {
+ get { return _isAutoSize; }
+ set { _isAutoSize = value; }
+ }
+ #endregion
+
+ #region Methods
+ /*
+ /// <summary>
+ /// Protected internal routine that draws the specified single bar (an individual "point")
+ /// of this series to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="CurveItem"/> object representing the
+ /// <see cref="Bar"/>'s to be drawn.</param>
+ /// <param name="index">
+ /// The zero-based index number for the single bar to be drawn.
+ /// </param>
+ /// <param name="pos">
+ /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.)
+ /// in the cluster of bars.
+ /// </param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="Bar"/></param>
+ /// <param name="barWidth">
+ /// The width of each bar, in pixels.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override protected void DrawSingleBar( Graphics g, GraphPane pane,
+ CurveItem curve,
+ int index, int pos, Axis baseAxis, Axis valueAxis,
+ float barWidth, float scaleFactor )
+ {
+ //float scaledSize = GetBarWidth( pane, baseAxis, scaleFactor );
+
+ // pixBase = pixel value for the bar center on the base axis
+ // pixValue = pixel value for the bar top on the value axis
+ // pixLow = pixel value for the bar bottom on the value axis
+ float pixBase, pixHiVal, pixLowVal;
+
+ // curBase = the scale value on the base axis of the current bar
+ // curValue = the scale value on the value axis of the current bar
+
+ double curBase, curLowVal, curHiVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ valueHandler.GetValues( curve, index, out curBase,
+ out curLowVal, out curHiVal );
+
+ barWidth = GetBarWidth( pane, baseAxis, scaleFactor );
+
+ // curLow = the scale value on the value axis for the bottom of the current bar
+ // Get a "low" value for the bottom of the bar and verify validity
+
+ if ( curLowVal == PointPair.Missing ||
+ System.Double.IsNaN( curLowVal ) ||
+ System.Double.IsInfinity( curLowVal ) )
+ curLowVal = 0;
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !curve.Points[index].IsInvalid )
+ {
+ // calculate a pixel value for the top of the bar on value axis
+ pixHiVal = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curHiVal );
+ // calculate a pixel value for the center of the bar on the base axis
+ pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curBase );
+
+ pixLowVal = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, index, curLowVal );
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - barWidth / 2.0F;
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - clusterWidth / 2.0F + clusterGap / 2.0F +
+ pos * ( barWidth + barGap );
+
+ // Draw the bar
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ this.Draw( g, pane, pixSide, pixSide + barWidth, pixLowVal,
+ pixHiVal, scaleFactor, true, curve.IsSelected,
+ curve.Points[index] );
+ else
+ this.Draw( g, pane, pixLowVal, pixHiVal, pixSide, pixSide + barWidth,
+ scaleFactor, true, curve.IsSelected,
+ curve.Points[index] );
+ }
+ }
+ */
+
+ /// <summary>
+ /// Returns the width of the bar, in pixels, based on the settings for
+ /// <see cref="Size"/> and <see cref="IsAutoSize"/>.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane"/> object.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> object that
+ /// represents the bar base (independent axis).</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The width of each bar, in pixel units</returns>
+ public float GetBarWidth( GraphPane pane, Axis baseAxis, float scaleFactor )
+ {
+ float width;
+
+ if ( _isAutoSize )
+ width = baseAxis._scale.GetClusterWidth( _userScaleSize ) /
+ ( 1.0F + pane._barSettings.MinClusterGap );
+ else
+ width = (float) ( _size * scaleFactor );
+
+ // use integral size
+ return (int)( width + 0.5f );
+ }
+
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/HiLowBarItem.cs b/ZedGraph/HiLowBarItem.cs
new file mode 100644
index 0000000..53e8285
--- /dev/null
+++ b/ZedGraph/HiLowBarItem.cs
@@ -0,0 +1,148 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates an "High-Low" Bar curve type that displays a bar in which both
+ /// the bottom and the top of the bar are set by data valuesfrom the
+ /// <see cref="PointPair"/> struct.
+ /// </summary>
+ /// <remarks>The <see cref="HiLowBarItem"/> type is intended for displaying
+ /// bars that cover a band of data, such as a confidence interval, "waterfall"
+ /// chart, etc. The position of each bar is set
+ /// according to the <see cref="PointPair"/> values. The independent axis
+ /// is assigned with <see cref="BarSettings.Base"/>, and is a
+ /// <see cref="BarBase"/> enum type. If <see cref="BarSettings.Base"/>
+ /// is set to <see cref="ZedGraph.BarBase.Y"/> or <see cref="ZedGraph.BarBase.Y2"/>, then
+ /// the bars will actually be horizontal, since the X axis becomes the
+ /// value axis and the Y or Y2 axis becomes the independent axis.</remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.18 $ $Date: 2007-11-03 04:41:28 $ </version>
+ [Serializable]
+ public class HiLowBarItem : BarItem, ICloneable, ISerializable
+ {
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="HiLowBarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ /// <param name="baseVal">An array of double precision values that define the
+ /// base value (the bottom) of the bars for this curve.
+ /// </param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="ZedGraph.Bar.Fill"/> and <see cref="ZedGraph.Bar.Border"/> properties.
+ /// </param>
+ public HiLowBarItem( string label, double[] x, double[] y, double[] baseVal, Color color ) :
+ this( label, new PointPairList( x, y, baseVal ), color )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="HiLowBarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value trio's that define
+ /// the X, Y, and lower dependent values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="ZedGraph.Bar.Fill"/> and <see cref="ZedGraph.Bar.Border"/> properties.
+ /// </param>
+ public HiLowBarItem( string label, IPointList points, Color color )
+ : base( label, points, color )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="HiLowBarItem"/> object from which to copy</param>
+ public HiLowBarItem( HiLowBarItem rhs ) : base( rhs )
+ {
+ _bar = rhs._bar.Clone(); // new HiLowBar( rhs.Bar );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ new public HiLowBarItem Clone()
+ {
+ return new HiLowBarItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected HiLowBarItem( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/IPointList.cs b/ZedGraph/IPointList.cs
new file mode 100644
index 0000000..faf8800
--- /dev/null
+++ b/ZedGraph/IPointList.cs
@@ -0,0 +1,57 @@
+//============================================================================
+//IPointList interface
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System;
+using System.Text;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An interface to a collection class containing data
+ /// that define the set of points to be displayed on the curve.
+ /// </summary>
+ /// <remarks>
+ /// This interface is designed to allow customized data abstraction. The default data
+ /// collection class is <see cref="PointPairList" />, however, you can define your own
+ /// data collection class using the <see cref="IPointList" /> interface.
+ /// </remarks>
+ /// <seealso cref="PointPairList" />
+ /// <seealso cref="BasicArrayPointList" />
+ ///
+ /// <author> John Champion</author>
+ /// <version> $Revision: 1.6 $ $Date: 2007-11-11 07:29:43 $ </version>
+ public interface IPointList : ICloneable
+ {
+ /// <summary>
+ /// Indexer to access a data point by its ordinal position in the collection.
+ /// </summary>
+ /// <remarks>
+ /// This is the standard interface that ZedGraph uses to access the data. Although
+ /// you must pass a <see cref="PointPair" /> here, your internal data storage format
+ /// can be anything.
+ /// </remarks>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// data point to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object instance.</value>
+ PointPair this[ int index ] { get; }
+ /// <summary>
+ /// Gets the number of points available in the list.
+ /// </summary>
+ int Count { get; }
+ }
+}
diff --git a/ZedGraph/IPointListEdit.cs b/ZedGraph/IPointListEdit.cs
new file mode 100644
index 0000000..fa1bbbf
--- /dev/null
+++ b/ZedGraph/IPointListEdit.cs
@@ -0,0 +1,88 @@
+//============================================================================
+//IPointListEdit interface
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System;
+using System.Text;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An interface to a collection class containing data
+ /// that define the set of points to be displayed on the curve.
+ /// </summary>
+ /// <remarks>
+ /// This interface is designed to allow customized data abstraction. The default data
+ /// collection class is <see cref="PointPairList" />, however, you can define your own
+ /// data collection class using the <see cref="IPointList" /> interface. This
+ /// <see cref="IPointListEdit" /> interface adds the ability to remove and add points
+ /// to the list, and so is used by the <see cref="CurveItem" /> class for the
+ /// <see cref="CurveItem.AddPoint(double,double)" />, <see cref="CurveItem.RemovePoint" />, and
+ /// <see cref="CurveItem.Clear" /> methods.
+ /// </remarks>
+ /// <seealso cref="PointPairList" />
+ /// <seealso cref="BasicArrayPointList" />
+ /// <seealso cref="IPointList" />
+ /// <seealso cref="FilteredPointList" />
+ ///
+ /// <author> John Champion</author>
+ /// <version> $Revision: 3.6 $ $Date: 2006-10-19 04:40:14 $ </version>
+ public interface IPointListEdit : IPointList
+ {
+ /// <summary>
+ /// Indexer to access a data point by its ordinal position in the collection.
+ /// </summary>
+ /// <remarks>
+ /// This is the standard interface that ZedGraph uses to access the data. Although
+ /// you must pass a <see cref="PointPair" /> here, your internal data storage format
+ /// can be anything.
+ /// </remarks>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// data point to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object instance.</value>
+ new PointPair this[int index] { get; set; }
+
+ /// <summary>
+ /// Appends a point to the end of the list. The data are passed in as a <see cref="PointPair" />
+ /// object.
+ /// </summary>
+ /// <param name="point">The <see cref="PointPair" /> object containing the data to be added.</param>
+ void Add( PointPair point );
+
+ /// <summary>
+ /// Appends a point to the end of the list. The data are passed in as two <see cref="Double" />
+ /// types.
+ /// </summary>
+ /// <param name="x">The <see cref="Double" /> value containing the X data to be added.</param>
+ /// <param name="y">The <see cref="Double" /> value containing the Y data to be added.</param>
+ /// <returns>The ordinal position (zero-based), at which the new point was added.</returns>
+ void Add( double x, double y );
+
+ /// <summary>
+ /// Removes a single data point from the list at the specified ordinal location
+ /// (zero based).
+ /// </summary>
+ void RemoveAt( int index );
+
+ /// <summary>
+ /// Clears all data points from the list. After calling this method,
+ /// <see cref="IPointList.Count" /> will be zero.
+ /// </summary>
+ void Clear();
+
+ }
+}
diff --git a/ZedGraph/ImageObj.cs b/ZedGraph/ImageObj.cs
new file mode 100644
index 0000000..24f37f1
--- /dev/null
+++ b/ZedGraph/ImageObj.cs
@@ -0,0 +1,341 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents an image object on the graph. A list of
+ /// <see cref="GraphObj"/> objects is maintained by the <see cref="GraphObjList"/>
+ /// collection class.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.2 $ $Date: 2006-09-09 17:32:01 $ </version>
+ [Serializable]
+ public class ImageObj : GraphObj, ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores the image. Use the public property <see cref="Image"/>
+ /// to access this value.
+ /// </summary>
+ private Image _image;
+ /// <summary>
+ /// Private field that determines if the image will be scaled to the output rectangle.
+ /// </summary>
+ /// <value>true to scale the image, false to draw the image unscaled, but clipped
+ /// to the destination rectangle</value>
+ private bool _isScaled;
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ImageObj"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ // Default text item properties
+ /// <summary>
+ /// Default value for the <see cref="ImageObj"/>
+ /// <see cref="ImageObj.IsScaled"/> property.
+ /// </summary>
+ public static bool IsScaled = true;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// The <see cref="System.Drawing.Image"/> object.
+ /// </summary>
+ /// <value> A <see cref="System.Drawing.Image"/> class reference. </value>
+ public Image Image
+ {
+ get { return _image; }
+ set { _image = value; }
+ }
+ /// <summary>
+ /// Gets or sets a property that determines if the image will be scaled to the
+ /// output rectangle (see <see cref="Location"/>).
+ /// </summary>
+ /// <value>true to scale the image, false to draw the image unscaled, but clipped
+ /// to the destination rectangle</value>
+ public bool IsScaled
+ {
+ get { return _isScaled; }
+ set { _isScaled = value; }
+ }
+ #endregion
+
+ #region Constructors
+ /// <overloads>Constructors for the <see cref="ImageObj"/> object</overloads>
+ /// <summary>
+ /// A default constructor that places a null <see cref="System.Drawing.Image"/> at a
+ /// default <see cref="RectangleF"/> of (0,0,1,1)
+ /// </summary>
+ public ImageObj() :
+ this( null, 0, 0, 1, 1 )
+ {
+ }
+
+ /// <summary>
+ /// A constructor that allows the <see cref="System.Drawing.Image"/> and
+ /// <see cref="RectangleF"/> location for the
+ /// <see cref="ImageObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="image">A <see cref="System.Drawing.Image"/> class that defines
+ /// the image</param>
+ /// <param name="rect">A <see cref="RectangleF"/> struct that defines the
+ /// image location, specifed in units based on the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ public ImageObj( Image image, RectangleF rect ) :
+ this( image, rect.X, rect.Y, rect.Width, rect.Height )
+ {
+ }
+
+ /// <overloads>Constructors for the <see cref="ImageObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the <see cref="System.Drawing.Image"/> and
+ /// <see cref="RectangleF"/> location for the
+ /// <see cref="ImageObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="image">A <see cref="System.Drawing.Image"/> class that defines
+ /// the image</param>
+ /// <param name="rect">A <see cref="RectangleF"/> struct that defines the
+ /// image location, specifed in units based on the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum value that
+ /// indicates what type of coordinate system the x and y parameters are
+ /// referenced to.</param>
+ /// <param name="alignH">The <see cref="ZedGraph.AlignH"/> enum that specifies
+ /// the horizontal alignment of the object with respect to the (x,y) location</param>
+ /// <param name="alignV">The <see cref="ZedGraph.AlignV"/> enum that specifies
+ /// the vertical alignment of the object with respect to the (x,y) location</param>
+ public ImageObj( Image image, RectangleF rect, CoordType coordType,
+ AlignH alignH, AlignV alignV ) :
+ base( rect.X, rect.Y, rect.Width, rect.Height, coordType,
+ alignH, alignV )
+ {
+ _image = image;
+ _isScaled = Default.IsScaled;
+ }
+
+ /// <overloads>Constructors for the <see cref="ImageObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the <see cref="System.Drawing.Image"/> and
+ /// individual <see cref="System.Single"/> coordinate locations for the
+ /// <see cref="ImageObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="image">A <see cref="System.Drawing.Image"/> class that defines
+ /// the image</param>
+ /// <param name="left">The position of the left side of the rectangle that defines the
+ /// <see cref="ImageObj"/> location. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="top">The position of the top side of the rectangle that defines the
+ /// <see cref="ImageObj"/> location. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="width">The width of the rectangle that defines the
+ /// <see cref="ImageObj"/> location. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="height">The height of the rectangle that defines the
+ /// <see cref="ImageObj"/> location. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ public ImageObj( Image image, double left, double top,
+ double width, double height ) :
+ base( left, top, width, height )
+ {
+ _image = image;
+ _isScaled = Default.IsScaled;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ImageObj"/> object from which to copy</param>
+ public ImageObj( ImageObj rhs ) : base( rhs )
+ {
+ _image = rhs._image;
+ _isScaled = rhs.IsScaled;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ImageObj Clone()
+ {
+ return new ImageObj( this );
+ }
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected ImageObj( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _image = (Image) info.GetValue( "image", typeof(Image) );
+ _isScaled = info.GetBoolean( "isScaled" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "image", _image );
+ info.AddValue( "isScaled", _isScaled );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this object to the specified <see cref="Graphics"/> device
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ if ( _image != null )
+ {
+ // Convert the rectangle coordinates from the user coordinate system
+ // to the screen coordinate system
+ RectangleF tmpRect = _location.TransformRect( pane );
+
+ if ( _isScaled )
+ g.DrawImage( _image, tmpRect );
+ else
+ {
+ Region clip = g.Clip;
+ g.SetClip( tmpRect );
+ g.DrawImageUnscaled( _image, Rectangle.Round( tmpRect ) );
+ g.SetClip( clip, CombineMode.Replace );
+ //g.DrawImageUnscaledAndClipped( image, Rectangle.Round( tmpRect ) );
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="ArrowObj"/>. The bounding box is calculated assuming a distance
+ /// of <see cref="GraphPane.Default.NearestTol"/> pixels around the arrow segment.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ if ( _image != null )
+ {
+ if ( ! base.PointInBox(pt, pane, g, scaleFactor ) )
+ return false;
+
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ RectangleF tmpRect = _location.TransformRect( pane );
+
+ return tmpRect.Contains( pt );
+ }
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// Determines the shape type and Coords values for this GraphObj
+ /// </summary>
+ override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor,
+ out string shape, out string coords )
+ {
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ RectangleF pixRect = _location.TransformRect( pane );
+
+ shape = "rect";
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixRect.Left, pixRect.Top, pixRect.Right, pixRect.Bottom );
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/JapaneseCandleStick.cs b/ZedGraph/JapaneseCandleStick.cs
new file mode 100644
index 0000000..e76e072
--- /dev/null
+++ b/ZedGraph/JapaneseCandleStick.cs
@@ -0,0 +1,484 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This class handles the drawing of the curve <see cref="JapaneseCandleStick"/> objects.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.10 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ public class JapaneseCandleStick : OHLCBar, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field to store the <see cref="Fill" /> class to be used for filling the
+ /// candlestick "bars" when the <see cref="StockPt.Close" /> value is greater than
+ /// the <see cref="StockPt.Open" /> value. See the public property
+ /// <see cref="RisingFill" /> to access this value.
+ /// </summary>
+ private Fill _risingFill;
+ /// <summary>
+ /// Private field to store the <see cref="Fill" /> class to be used for filling the
+ /// candlestick "bars" when the <see cref="StockPt.Close" /> value is less than
+ /// the <see cref="StockPt.Open" /> value. See the public property
+ /// <see cref="FallingFill" /> to access this value.
+ /// </summary>
+ private Fill _fallingFill;
+
+ /// <summary>
+ /// Private field to store the <see cref="Border" /> class to be used for drawing the
+ /// candlestick "bars" when the <see cref="StockPt.Close" /> value is greater than
+ /// the <see cref="StockPt.Open" /> value. See the public property
+ /// <see cref="RisingBorder" /> to access this value.
+ /// </summary>
+ private Border _risingBorder;
+ /// <summary>
+ /// Private field to store the <see cref="Border" /> class to be used for drawing the
+ /// candlestick "bars" when the <see cref="StockPt.Close" /> value is less than
+ /// the <see cref="StockPt.Open" /> value. See the public property
+ /// <see cref="FallingBorder" /> to access this value.
+ /// </summary>
+ private Border _fallingBorder;
+
+ /// <summary>
+ /// Private field that stores the CandleStick color when the <see cref="StockPt.Close" />
+ /// value is less than the <see cref="StockPt.Open" /> value. Use the public
+ /// property <see cref="FallingColor"/> to access this value.
+ /// </summary>
+ protected Color _fallingColor;
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ZedGraph.JapaneseCandleStick"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ /// <summary>
+ /// The default fillcolor for drawing the rising case CandleSticks
+ /// (<see cref="JapaneseCandleStick.RisingFill"/> property).
+ /// </summary>
+ public static Color RisingColor = Color.White;
+ /// <summary>
+ /// The default fillcolor for drawing the falling case CandleSticks
+ /// (<see cref="JapaneseCandleStick.FallingFill"/> property).
+ /// </summary>
+ public static Color FallingColor = Color.Black;
+
+ /// <summary>
+ /// The default color for the border of the rising CandleSticks
+ /// (<see cref="JapaneseCandleStick.RisingBorder" /> property).
+ /// </summary>
+ public static Color RisingBorder = Color.Black;
+ /// <summary>
+ /// The default color for the border of the falling CandleSticks
+ /// (<see cref="JapaneseCandleStick.FallingBorder" /> property).
+ /// </summary>
+ public static Color FallingBorder = Color.Black;
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="Fill" /> class that is used to fill the candlestick
+ /// "bars" when the <see cref="StockPt.Close" /> value is greater than the
+ /// <see cref="StockPt.Open" /> value.
+ /// </summary>
+ public Fill RisingFill
+ {
+ get { return _risingFill; }
+ set { _risingFill = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="Fill" /> class that is used to fill the candlestick
+ /// "bars" when the <see cref="StockPt.Close" /> value is less than the
+ /// <see cref="StockPt.Open" /> value.
+ /// </summary>
+ public Fill FallingFill
+ {
+ get { return _fallingFill; }
+ set { _fallingFill = value; }
+ }
+
+ /// <summary>
+ /// The <see cref="Border" /> instance to be used for drawing the border frame of
+ /// the candlestick "bars" when the <see cref="StockPt.Close" /> value is greater than the
+ /// <see cref="StockPt.Open" /> value.
+ /// </summary>
+ public Border RisingBorder
+ {
+ get { return _risingBorder; }
+ set { _risingBorder = value; }
+ }
+ /// <summary>
+ /// The <see cref="Border" /> instance to be used for drawing the border frame of
+ /// the candlestick "bars" when the <see cref="StockPt.Close" /> value is less than the
+ /// <see cref="StockPt.Open" /> value.
+ /// </summary>
+ public Border FallingBorder
+ {
+ get { return _fallingBorder; }
+ set { _fallingBorder = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> data for this
+ /// <see cref="JapaneseCandleStick"/> when the value of the candlestick is
+ /// falling.
+ /// </summary>
+ /// <remarks>This property only controls the color of
+ /// the vertical line when the value is falling. The rising color is controlled
+ /// by the <see cref="LineBase.Color" /> property.
+ /// </remarks>
+ public Color FallingColor
+ {
+ get { return _fallingColor; }
+ set { _fallingColor = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="JapaneseCandleStick"/> properties to
+ /// default values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public JapaneseCandleStick() : base()
+ {
+ _risingFill = new Fill( Default.RisingColor );
+ _fallingFill = new Fill( Default.FallingColor );
+
+ _risingBorder = new Border( Default.RisingBorder, LineBase.Default.Width );
+ _fallingBorder = new Border( Default.FallingBorder, LineBase.Default.Width );
+
+ _fallingColor = Default.FallingColor;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="JapaneseCandleStick"/> object from which to copy</param>
+ public JapaneseCandleStick( JapaneseCandleStick rhs ) : base( rhs )
+ {
+ _risingFill = rhs._risingFill.Clone();
+ _fallingFill = rhs._fallingFill.Clone();
+
+ _risingBorder = rhs._risingBorder.Clone();
+ _fallingBorder = rhs._fallingBorder.Clone();
+
+ _fallingColor = rhs._fallingColor;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new JapaneseCandleStick Clone()
+ {
+ return new JapaneseCandleStick( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected JapaneseCandleStick( SerializationInfo info, StreamingContext context ) :
+ base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _risingFill = (Fill)info.GetValue( "risingFill", typeof( Fill ) );
+ _fallingFill = (Fill)info.GetValue( "fallingFill", typeof( Fill ) );
+ _risingBorder = (Border)info.GetValue( "risingBorder", typeof( Border ) );
+ _fallingBorder = (Border)info.GetValue( "fallingBorder", typeof( Border ) );
+
+ if ( schema2 >= 11 )
+ _fallingColor = (Color) info.GetValue( "fallingColor", typeof( Color ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "risingFill", _risingFill );
+ info.AddValue( "fallingFill", _fallingFill );
+ info.AddValue( "risingBorder", _risingBorder );
+ info.AddValue( "fallingBorder", _fallingBorder );
+ info.AddValue( "fallingColor", _fallingColor );
+ }
+
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Draw the <see cref="JapaneseCandleStick"/> to the specified <see cref="Graphics"/>
+ /// device at the specified location.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="isXBase">boolean value that indicates if the "base" axis for this
+ /// <see cref="JapaneseCandleStick"/> is the X axis. True for an <see cref="XAxis"/> base,
+ /// false for a <see cref="YAxis"/> or <see cref="Y2Axis"/> base.</param>
+ /// <param name="pixBase">The independent axis position of the center of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixHigh">The high value position of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixLow">The low value position of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixOpen">The opening value position of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixClose">The closing value position of the candlestick in
+ /// pixel units</param>
+ /// <param name="halfSize">The scaled width of one-half of a bar, in pixels</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.</param>
+ /// <param name="pen">A pen with the <see cref="Color"/> attribute for this
+ /// <see cref="JapaneseCandleStick"/></param>
+ /// <param name="fill">
+ /// The <see cref="Fill" /> instance to be used for filling this
+ /// <see cref="JapaneseCandleStick" />
+ /// </param>
+ /// <param name="border">The <see cref="Border" /> instance to be used for drawing the
+ /// border around the <see cref="JapaneseCandleStick" /> filled box</param>
+ /// <param name="pt">The <see cref="PointPair" /> to be used for determining the
+ /// <see cref="Fill" />, just in case it's a <see cref="FillType.GradientByX" />,
+ /// <see cref="FillType.GradientByY" />, or
+ /// <see cref="FillType.GradientByZ" /> <see cref="FillType" /></param>
+ public void Draw( Graphics g, GraphPane pane, bool isXBase,
+ float pixBase, float pixHigh, float pixLow,
+ float pixOpen, float pixClose, float halfSize,
+ float scaleFactor, Pen pen, Fill fill, Border border, PointPair pt )
+ {
+ //float halfSize = (int) ( _size * scaleFactor / 2.0f + 0.5f );
+
+ if ( pixBase != PointPair.Missing && Math.Abs( pixLow ) < 1000000 &&
+ Math.Abs( pixHigh ) < 1000000)
+ {
+ RectangleF rect;
+ if ( isXBase )
+ {
+ rect = new RectangleF( pixBase - halfSize, Math.Min( pixOpen, pixClose ),
+ halfSize * 2.0f, Math.Abs( pixOpen - pixClose ) );
+
+ g.DrawLine( pen, pixBase, pixHigh, pixBase, pixLow );
+ }
+ else
+ {
+ rect = new RectangleF( Math.Min( pixOpen, pixClose ), pixBase - halfSize,
+ Math.Abs( pixOpen - pixClose ), halfSize * 2.0f );
+
+ g.DrawLine( pen, pixHigh, pixBase, pixLow, pixBase );
+ }
+
+ if ( _isOpenCloseVisible && Math.Abs( pixOpen ) < 1000000 &&
+ Math.Abs( pixClose ) < 1000000 )
+ {
+ if ( rect.Width == 0 )
+ rect.Width = 1;
+ if ( rect.Height == 0 )
+ rect.Height = 1;
+
+ fill.Draw( g, rect, pt );
+ border.Draw( g, pane, scaleFactor, rect );
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Draw all the <see cref="JapaneseCandleStick"/>'s to the specified <see cref="Graphics"/>
+ /// device as a candlestick at each defined point.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="JapaneseCandleStickItem"/> object representing the
+ /// <see cref="JapaneseCandleStick"/>'s to be drawn.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="JapaneseCandleStick"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="JapaneseCandleStick"/></param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, JapaneseCandleStickItem curve,
+ Axis baseAxis, Axis valueAxis, float scaleFactor )
+ {
+ //ValueHandler valueHandler = new ValueHandler( pane, false );
+
+ float pixBase, pixHigh, pixLow, pixOpen, pixClose;
+
+ if ( curve.Points != null )
+ {
+ //float halfSize = _size * scaleFactor;
+ float halfSize = GetBarWidth( pane, baseAxis, scaleFactor );
+
+ Color tColor = _color;
+ Color tFallingColor = _fallingColor;
+ float tPenWidth = _width;
+ Fill tRisingFill = _risingFill;
+ Fill tFallingFill = _fallingFill;
+ Border tRisingBorder = _risingBorder;
+ Border tFallingBorder = _fallingBorder;
+ if ( curve.IsSelected )
+ {
+ tColor = Selection.Border.Color;
+ tFallingColor = Selection.Border.Color;
+ tPenWidth = Selection.Border.Width;
+ tRisingFill = Selection.Fill;
+ tFallingFill = Selection.Fill;
+ tRisingBorder = Selection.Border;
+ tFallingBorder = Selection.Border;
+
+ }
+
+ using ( Pen risingPen = new Pen( tColor, tPenWidth ) )
+ using ( Pen fallingPen = new Pen( tFallingColor, tPenWidth ) )
+ {
+ // Loop over each defined point
+ for ( int i = 0; i < curve.Points.Count; i++ )
+ {
+ PointPair pt = curve.Points[i];
+ double date = pt.X;
+ double high = pt.Y;
+ double low = pt.Z;
+ double open = PointPair.Missing;
+ double close = PointPair.Missing;
+ if ( pt is StockPt )
+ {
+ open = ( pt as StockPt ).Open;
+ close = ( pt as StockPt ).Close;
+ }
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !curve.Points[i].IsInvalid3D &&
+ ( date > 0 || !baseAxis._scale.IsLog ) &&
+ ( ( high > 0 && low > 0 ) || !valueAxis._scale.IsLog ) )
+ {
+ pixBase = (int) ( baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, date ) + 0.5 );
+ //pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, date );
+ pixHigh = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, high );
+ pixLow = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, low );
+ if ( PointPair.IsValueInvalid( open ) )
+ pixOpen = Single.MaxValue;
+ else
+ pixOpen = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, open );
+
+ if ( PointPair.IsValueInvalid( close ) )
+ pixClose = Single.MaxValue;
+ else
+ pixClose = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, close );
+
+ if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
+ {
+ using ( Pen tPen = GetPen( pane, scaleFactor, pt ) )
+ Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis,
+ pixBase, pixHigh, pixLow, pixOpen,
+ pixClose, halfSize, scaleFactor,
+ ( tPen ),
+ ( close > open ? tRisingFill : tFallingFill ),
+ ( close > open ? tRisingBorder : tFallingBorder ), pt );
+ }
+ else
+ Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis,
+ pixBase, pixHigh, pixLow, pixOpen,
+ pixClose, halfSize, scaleFactor,
+ ( close > open ? risingPen : fallingPen ),
+ ( close > open ? tRisingFill : tFallingFill ),
+ ( close > open ? tRisingBorder : tFallingBorder ), pt );
+ }
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/JapaneseCandleStickItem.cs b/ZedGraph/JapaneseCandleStickItem.cs
new file mode 100644
index 0000000..f494ef9
--- /dev/null
+++ b/ZedGraph/JapaneseCandleStickItem.cs
@@ -0,0 +1,352 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates a Japanese CandleStick curve type that displays a vertical (or horizontal)
+ /// line displaying the range of data values at each sample point, plus a filled bar
+ /// signifying the opening and closing value for the sample.
+ /// </summary>
+ /// <remarks>For this type to work properly, your <see cref="IPointList" /> must contain
+ /// <see cref="StockPt" /> objects, rather than ordinary <see cref="PointPair" /> types.
+ /// This is because the <see cref="OHLCBarItem"/> type actually displays 5 data values
+ /// but the <see cref="PointPair" /> only stores 3 data values. The <see cref="StockPt" />
+ /// stores <see cref="StockPt.Date" />, <see cref="StockPt.Close" />,
+ /// <see cref="StockPt.Open" />, <see cref="StockPt.High" />, and
+ /// <see cref="StockPt.Low" /> members.
+ /// For a JapaneseCandleStick chart, the range between opening and closing values
+ /// is drawn as a filled bar, with the filled color different
+ /// (<see cref="ZedGraph.JapaneseCandleStick.RisingFill" />) for the case of
+ /// <see cref="StockPt.Close" />
+ /// higher than <see cref="StockPt.Open" />, and
+ /// <see cref="ZedGraph.JapaneseCandleStick.FallingFill" />
+ /// for the reverse. The width of the bar is controlled
+ /// by the <see cref="ZedGraph.OHLCBar.Size" /> property, which is specified in
+ /// points (1/72nd inch), and scaled according to <see cref="PaneBase.CalcScaleFactor" />.
+ /// The candlesticks are drawn horizontally or vertically depending on the
+ /// value of <see cref="BarSettings.Base"/>, which is a
+ /// <see cref="ZedGraph.BarBase"/> enum type.</remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.6 $ $Date: 2007-12-31 00:23:05 $ </version>
+ [Serializable]
+ public class JapaneseCandleStickItem : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="ZedGraph.OHLCBar"/>
+ /// class defined for this <see cref="OHLCBarItem"/>. Use the public
+ /// property <see cref="OHLCBar"/> to access this value.
+ /// </summary>
+ ///
+ private JapaneseCandleStick _stick;
+
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets a reference to the <see cref="JapaneseCandleStick"/> class defined
+ /// for this <see cref="JapaneseCandleStickItem"/>.
+ /// </summary>
+ public JapaneseCandleStick Stick
+ {
+ get { return _stick; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return pane._barSettings.Base == BarBase.X;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <remarks>
+ /// IsZIncluded is true for <see cref="JapaneseCandleStickItem" /> objects, since the Y and Z
+ /// values are defined as the High and Low values for the day.</remarks>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return true;
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Create a new <see cref="OHLCBarItem"/>, specifying only the legend label.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ public JapaneseCandleStickItem( string label )
+ : base( label )
+ {
+ _stick = new JapaneseCandleStick();
+ }
+
+ /// <summary>
+ /// Create a new <see cref="JapaneseCandleStickItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="points">An <see cref="IPointList"/> of double precision values that define
+ /// the Date, Close, Open, High, and Low values for the curve. Note that this
+ /// <see cref="IPointList" /> should contain <see cref="StockPt" /> items rather
+ /// than <see cref="PointPair" /> items.
+ /// </param>
+ public JapaneseCandleStickItem( string label, IPointList points )
+ : base( label, points )
+ {
+ _stick = new JapaneseCandleStick();
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="JapaneseCandleStickItem"/> object from which to copy</param>
+ public JapaneseCandleStickItem( JapaneseCandleStickItem rhs )
+ : base( rhs )
+ {
+ _stick = rhs._stick.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public JapaneseCandleStickItem Clone()
+ {
+ return new JapaneseCandleStickItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected JapaneseCandleStickItem( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _stick = (JapaneseCandleStick) info.GetValue( "stick",
+ typeof( JapaneseCandleStick ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "stick", _stick );
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="OHLCBarItem"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">The ordinal position of the current <see cref="OHLCBarItem"/>
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( _isVisible )
+ {
+ _stick.Draw( g, pane, this, this.BaseAxis( pane ),
+ this.ValueAxis( pane ), scaleFactor );
+ }
+ }
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="OHLCBarItem"/> at the specified location
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect,
+ float scaleFactor )
+ {
+ float pixBase, pixHigh, pixLow, pixOpen, pixClose;
+
+ if ( pane._barSettings.Base == BarBase.X )
+ {
+ pixBase = rect.Left + rect.Width / 2.0F;
+ pixHigh = rect.Top;
+ pixLow = rect.Bottom;
+ pixOpen = pixHigh + rect.Height / 3;
+ pixClose = pixLow - rect.Height / 3;
+ }
+ else
+ {
+ pixBase = rect.Top + rect.Height / 2.0F;
+ pixHigh = rect.Right;
+ pixLow = rect.Left;
+ pixOpen = pixHigh - rect.Width / 3;
+ pixClose = pixLow + rect.Width / 3;
+ }
+
+ Axis baseAxis = BaseAxis( pane );
+ //float halfSize = _stick.GetBarWidth( pane, baseAxis, scaleFactor );
+ float halfSize = 2 * scaleFactor;
+
+ using ( Pen pen = new Pen( _stick.Color, _stick._width ) )
+ {
+ _stick.Draw( g, pane, pane._barSettings.Base == BarBase.X, pixBase, pixHigh,
+ pixLow, pixOpen, pixClose, halfSize, scaleFactor, pen,
+ _stick.RisingFill,
+ _stick.RisingBorder, null );
+ }
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ override public bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = string.Empty;
+
+ if ( i < 0 || i >= _points.Count )
+ return false;
+
+ Axis valueAxis = ValueAxis( pane );
+ Axis baseAxis = BaseAxis( pane );
+
+ float halfSize = _stick.Size * pane.CalcScaleFactor();
+
+ PointPair pt = _points[i];
+ double date = pt.X;
+ double high = pt.Y;
+ double low = pt.Z;
+
+ if ( !pt.IsInvalid3D &&
+ ( date > 0 || !baseAxis._scale.IsLog ) &&
+ ( ( high > 0 && low > 0 ) || !valueAxis._scale.IsLog ) )
+ {
+ float pixBase, pixHigh, pixLow;
+ pixBase = baseAxis.Scale.Transform( _isOverrideOrdinal, i, date );
+ pixHigh = valueAxis.Scale.Transform( _isOverrideOrdinal, i, high );
+ pixLow = valueAxis.Scale.Transform( _isOverrideOrdinal, i, low );
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - halfSize;
+
+ // Draw the bar
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixSide, pixLow,
+ pixSide + halfSize * 2, pixHigh );
+ else
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixLow, pixSide,
+ pixHigh, pixSide + halfSize * 2 );
+
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Label.cs b/ZedGraph/Label.cs
new file mode 100644
index 0000000..7ee6200
--- /dev/null
+++ b/ZedGraph/Label.cs
@@ -0,0 +1,201 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles the data associated with text title and its associated font
+ /// properties
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.2 $ $Date: 2007-03-11 02:08:16 $ </version>
+ [Serializable]
+ public class Label : ICloneable, ISerializable
+ {
+ /// <summary>
+ /// private field that stores the <see cref="string" /> text for this label
+ /// </summary>
+ internal string _text;
+ /// <summary>
+ /// private field that stores the <see cref="FontSpec" /> font properties for this label
+ /// </summary>
+ internal FontSpec _fontSpec;
+ /// <summary>
+ /// private field that determines if this label will be displayed.
+ /// </summary>
+ internal bool _isVisible;
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to build an <see cref="AxisLabel" /> from the text and the
+ /// associated font properties.
+ /// </summary>
+ /// <param name="text">The <see cref="string" /> representing the text to be
+ /// displayed</param>
+ /// <param name="fontFamily">The <see cref="String" /> font family name</param>
+ /// <param name="fontSize">The size of the font in points and scaled according
+ /// to the <see cref="PaneBase.CalcScaleFactor" /> logic.</param>
+ /// <param name="color">The <see cref="Color" /> instance representing the color
+ /// of the font</param>
+ /// <param name="isBold">true for a bold font face</param>
+ /// <param name="isItalic">true for an italic font face</param>
+ /// <param name="isUnderline">true for an underline font face</param>
+ public Label( string text, string fontFamily, float fontSize, Color color, bool isBold,
+ bool isItalic, bool isUnderline )
+ {
+ _text = ( text == null ) ? string.Empty : text;
+
+ _fontSpec = new FontSpec( fontFamily, fontSize, color, isBold, isItalic, isUnderline );
+ _isVisible = true;
+ }
+
+ /// <summary>
+ /// Constructor that builds a <see cref="Label" /> from a text <see cref="string" />
+ /// and a <see cref="FontSpec" /> instance.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <param name="fontSpec"></param>
+ public Label( string text, FontSpec fontSpec )
+ {
+ _text = (text == null) ? string.Empty : text;
+
+ _fontSpec = fontSpec;
+ _isVisible = true;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">the <see cref="Label" /> instance to be copied.</param>
+ public Label( Label rhs )
+ {
+ if (rhs._text != null)
+ _text = (string)rhs._text.Clone();
+ else
+ _text = string.Empty;
+
+ _isVisible = rhs._isVisible;
+ if ( rhs._fontSpec != null )
+ _fontSpec = rhs._fontSpec.Clone();
+ else
+ _fontSpec = null;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Label Clone()
+ {
+ return new Label( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// The <see cref="String" /> text to be displayed
+ /// </summary>
+ public string Text
+ {
+ get { return _text; }
+ set { _text = value; }
+ }
+
+ /// <summary>
+ /// A <see cref="ZedGraph.FontSpec" /> instance representing the font properties
+ /// for the displayed text.
+ /// </summary>
+ public FontSpec FontSpec
+ {
+ get { return _fontSpec; }
+ set { _fontSpec = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a boolean value that determines whether or not this label will be displayed.
+ /// </summary>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Label( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _text = info.GetString( "text" );
+ _isVisible = info.GetBoolean( "isVisible" );
+ _fontSpec = (FontSpec) info.GetValue( "fontSpec", typeof( FontSpec ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "text", _text );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "fontSpec", _fontSpec );
+ }
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/Legend.cs b/ZedGraph/Legend.cs
new file mode 100644
index 0000000..7cfc11a
--- /dev/null
+++ b/ZedGraph/Legend.cs
@@ -0,0 +1,1037 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This class encapsulates the chart <see cref="Legend"/> that is displayed
+ /// in the <see cref="GraphPane"/>
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.41 $ $Date: 2007-08-11 19:24:55 $ </version>
+ [Serializable]
+ public class Legend : ICloneable, ISerializable
+ {
+ #region private Fields
+
+ /// <summary> Private field to hold the bounding rectangle around the legend.
+ /// This bounding rectangle varies with the number of legend entries, font sizes,
+ /// etc., and is re-calculated by <see cref="Legend.CalcRect"/> at each redraw.
+ /// Use the public readonly property <see cref="Legend.Rect"/> to access this
+ /// rectangle.
+ /// </summary>
+ private RectangleF _rect;
+ /// <summary>Private field to hold the legend location setting. This field
+ /// contains the <see cref="LegendPos"/> enum type to specify the area of
+ /// the graph where the legend will be positioned. Use the public property
+ /// <see cref="LegendPos"/> to access this value.
+ /// </summary>
+ /// <seealso cref="Default.Position"/>
+ private LegendPos _position;
+ /// <summary>
+ /// Private field to enable/disable horizontal stacking of the legend entries.
+ /// If this value is false, then the legend entries will always be a single column.
+ /// Use the public property <see cref="IsHStack"/> to access this value.
+ /// </summary>
+ /// <seealso cref="Default.IsHStack"/>
+ private bool _isHStack;
+ /// <summary>
+ /// Private field to enable/disable drawing of the entire legend.
+ /// If this value is false, then the legend will not be drawn.
+ /// Use the public property <see cref="IsVisible"/> to access this value.
+ /// </summary>
+ private bool _isVisible;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Legend"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Border"/> data for this
+ /// <see cref="Legend"/>. Use the public property <see cref="Border"/> to
+ /// access this value.
+ /// </summary>
+ private Border _border;
+ /// <summary>
+ /// Private field to maintain the <see cref="FontSpec"/> class that
+ /// maintains font attributes for the entries in this legend. Use
+ /// the <see cref="FontSpec"/> property to access this class.
+ /// </summary>
+ private FontSpec _fontSpec;
+ /// <summary>
+ /// Private field to maintain the <see cref="Legend"/> location. This object
+ /// is only applicable if the <see cref="Position"/> property is set to
+ /// <see cref="LegendPos.Float"/>.
+ /// </summary>
+ private Location _location;
+
+ /// <summary>
+ /// Private temporary field to maintain the number of columns (horizontal stacking) to be used
+ /// for drawing the <see cref="Legend"/>. This value is only valid during a draw operation.
+ /// </summary>
+ private int _hStack;
+ /// <summary>
+ /// Private temporary field to maintain the width of each column in the
+ /// <see cref="Legend"/>. This value is only valid during a draw operation.
+ /// </summary>
+ private float _legendItemWidth;
+ /// <summary>
+ /// Private temporary field to maintain the height of each row in the
+ /// <see cref="Legend"/>. This value is only valid during a draw operation.
+ /// </summary>
+ private float _legendItemHeight;
+
+ /// <summary>
+ /// Private field to store the gap between the legend and the chart rectangle.
+ /// </summary>
+ private float _gap;
+
+ // CJBL
+ /// <summary>
+ /// Private field to select output order of legend entries.
+ /// </summary>
+ private bool _isReverse;
+
+ /// <summary>
+ /// Private temporary field to maintain the characteristic "gap" for the legend.
+ /// This is normal the height of the largest font in the legend.
+ /// This value is only valid during a draw operation.
+ /// </summary>
+ private float _tmpSize;
+
+ /// <summary>
+ /// Private field to enable/diable drawing the line and symbol samples in the
+ /// legend.
+ /// </summary>
+ private bool _isShowLegendSymbols;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Legend"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default Legend properties
+ /// <summary>
+ /// The default pen width for the <see cref="Legend"/> border border.
+ /// (<see cref="ZedGraph.LineBase.Width"/> property). Units are in pixels.
+ /// </summary>
+ public static float BorderWidth = 1;
+ /// <summary>
+ /// The default color for the <see cref="Legend"/> border border.
+ /// (<see cref="ZedGraph.LineBase.Color"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default color for the <see cref="Legend"/> background.
+ /// (<see cref="ZedGraph.Fill.Color"/> property). Use of this
+ /// color depends on the status of the <see cref="ZedGraph.Fill.Type"/>
+ /// property.
+ /// </summary>
+ public static Color FillColor = Color.White;
+ /// <summary>
+ /// The default custom brush for filling in this <see cref="Legend"/>.
+ /// </summary>
+ public static Brush FillBrush = null;
+ /// <summary>
+ /// The default fill mode for the <see cref="Legend"/> background.
+ /// </summary>
+ public static FillType FillType = FillType.Brush;
+ /// <summary>
+ /// The default location for the <see cref="Legend"/> on the graph
+ /// (<see cref="Legend.Location"/> property). This property is
+ /// defined as a <see cref="LegendPos"/> enumeration.
+ /// </summary>
+ public static LegendPos Position = LegendPos.Top;
+ /// <summary>
+ /// The default border mode for the <see cref="Legend"/>.
+ /// (<see cref="ZedGraph.LineBase.IsVisible"/> property). true
+ /// to draw a border around the <see cref="Legend.Rect"/>,
+ /// false otherwise.
+ /// </summary>
+ public static bool IsBorderVisible = true;
+ /// <summary>
+ /// The default display mode for the <see cref="Legend"/>.
+ /// (<see cref="Legend.IsVisible"/> property). true
+ /// to show the legend,
+ /// false to hide it.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// The default fill mode for the <see cref="Legend"/> background
+ /// (<see cref="ZedGraph.Fill.Type"/> property).
+ /// true to fill-in the background with color,
+ /// false to leave the background transparent.
+ /// </summary>
+ public static bool IsFilled = true;
+ /// <summary>
+ /// The default horizontal stacking mode for the <see cref="Legend"/>
+ /// (<see cref="Legend.IsHStack"/> property).
+ /// true to allow horizontal legend item stacking, false to allow
+ /// only vertical legend orientation.
+ /// </summary>
+ public static bool IsHStack = true;
+
+ /// <summary>
+ /// The default font family for the <see cref="Legend"/> entries
+ /// (<see cref="ZedGraph.FontSpec.Family"/> property).
+ /// </summary>
+ public static string FontFamily = "Arial";
+ /// <summary>
+ /// The default font size for the <see cref="Legend"/> entries
+ /// (<see cref="ZedGraph.FontSpec.Size"/> property). Units are
+ /// in points (1/72 inch).
+ /// </summary>
+ public static float FontSize = 12;
+ /// <summary>
+ /// The default font color for the <see cref="Legend"/> entries
+ /// (<see cref="ZedGraph.FontSpec.FontColor"/> property).
+ /// </summary>
+ public static Color FontColor = Color.Black;
+ /// <summary>
+ /// The default font bold mode for the <see cref="Legend"/> entries
+ /// (<see cref="ZedGraph.FontSpec.IsBold"/> property). true
+ /// for a bold typeface, false otherwise.
+ /// </summary>
+ public static bool FontBold = false;
+ /// <summary>
+ /// The default font italic mode for the <see cref="Legend"/> entries
+ /// (<see cref="ZedGraph.FontSpec.IsItalic"/> property). true
+ /// for an italic typeface, false otherwise.
+ /// </summary>
+ public static bool FontItalic = false;
+ /// <summary>
+ /// The default font underline mode for the <see cref="Legend"/> entries
+ /// (<see cref="ZedGraph.FontSpec.IsUnderline"/> property). true
+ /// for an underlined typeface, false otherwise.
+ /// </summary>
+ public static bool FontUnderline = false;
+ /// <summary>
+ /// The default color for filling in the scale text background
+ /// (see <see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FontFillColor = Color.White;
+ /// <summary>
+ /// The default custom brush for filling in the scale text background
+ /// (see <see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FontFillBrush = null;
+ /// <summary>
+ /// The default fill mode for filling in the scale text background
+ /// (see <see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FontFillType = FillType.None;
+
+ /// <summary>
+ /// The default gap size between the legend and the <see cref="Chart.Rect" />.
+ /// This is the default value of <see cref="Legend.Gap" />.
+ /// </summary>
+ public static float Gap = 0.5f;
+
+ /// <summary>
+ /// Default value for the <see cref="Legend.IsReverse" /> property.
+ /// </summary>
+ public static bool IsReverse = false;
+
+ /// <summary>
+ /// Default value for the <see cref="Legend.IsShowLegendSymbols" /> property.
+ /// </summary>
+ public static bool IsShowLegendSymbols = true;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Get the bounding rectangle for the <see cref="Legend"/> in screen coordinates
+ /// </summary>
+ /// <value>A screen rectangle in pixel units</value>
+ public RectangleF Rect
+ {
+ get { return _rect; }
+ }
+ /// <summary>
+ /// Access to the <see cref="ZedGraph.FontSpec"/> class used to render
+ /// the <see cref="Legend"/> entries
+ /// </summary>
+ /// <value>A reference to a <see cref="Legend"/> object</value>
+ /// <seealso cref="Default.FontColor"/>
+ /// <seealso cref="Default.FontBold"/>
+ /// <seealso cref="Default.FontItalic"/>
+ /// <seealso cref="Default.FontUnderline"/>
+ /// <seealso cref="Default.FontFamily"/>
+ /// <seealso cref="Default.FontSize"/>
+ public FontSpec FontSpec
+ {
+ get { return _fontSpec; }
+ set
+ {
+ if ( value == null )
+ throw new ArgumentNullException( "Uninitialized FontSpec in Legend" );
+ _fontSpec = value;
+ }
+ }
+ /// <summary>
+ /// Gets or sets a property that shows or hides the <see cref="Legend"/> entirely
+ /// </summary>
+ /// <value> true to show the <see cref="Legend"/>, false to hide it </value>
+ /// <seealso cref="Default.IsVisible"/>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+ /// <summary>
+ /// The <see cref="Border"/> class used to draw the border border around this <see cref="Legend"/>.
+ /// </summary>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Legend"/> background.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Sets or gets a property that allows the <see cref="Legend"/> items to
+ /// stack horizontally in addition to the vertical stacking
+ /// </summary>
+ /// <value>true to allow horizontal stacking, false otherwise
+ /// </value>
+ /// <seealso cref="Default.IsHStack"/>
+ public bool IsHStack
+ {
+ get { return _isHStack; }
+ set { _isHStack = value; }
+ }
+ /// <summary>
+ /// Sets or gets the location of the <see cref="Legend"/> on the
+ /// <see cref="GraphPane"/> using the <see cref="LegendPos"/> enum type
+ /// </summary>
+ /// <seealso cref="Default.Position"/>
+ public LegendPos Position
+ {
+ get { return _position; }
+ set { _position = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="Location"/> data for the <see cref="Legend"/>.
+ /// This property is only applicable if <see cref="Position"/> is set
+ /// to <see cref="LegendPos.Float"/>.
+ /// </summary>
+ public Location Location
+ {
+ get { return _location; }
+ set { _location = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the gap size between the legend and the <see cref="Chart.Rect" />.
+ /// </summary>
+ /// <remarks>
+ /// This is expressed as a fraction of the largest scaled character height for any
+ /// of the fonts used in the legend. Each <see cref="CurveItem" /> in the legend can
+ /// optionally have its own <see cref="FontSpec" /> specification.
+ /// </remarks>
+ public float Gap
+ {
+ get { return _gap; }
+ set { _gap = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the legend entries are displayed in normal order
+ /// (matching the order in the <see cref="CurveList" />, or in reverse order.
+ /// </summary>
+ public bool IsReverse
+ {
+ get { return _isReverse; }
+ set { _isReverse = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether the line and symbol keys will be displayed
+ /// in the legend.
+ /// </summary>
+ /// <remarks>
+ /// Note: If this value is set to false (so that only the curve label text is displayed
+ /// with no legend keys), then the color of the font for the legend entry of each curve
+ /// will automatically be set to match the <see cref="CurveItem.Color"/> setting for that curve.
+ /// You can override this behavior by specifying a specific font to be used for each
+ /// individual curve with the <see cref="ZedGraph.Label.FontSpec">CurveItem.Label.FontSpec</see>
+ /// property.
+ /// </remarks>
+ public bool IsShowLegendSymbols
+ {
+ get { return _isShowLegendSymbols; }
+ set { _isShowLegendSymbols = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default constructor that sets all <see cref="Legend"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public Legend()
+ {
+ _position = Default.Position;
+ _isHStack = Default.IsHStack;
+ _isVisible = Default.IsVisible;
+ this.Location = new Location( 0, 0, CoordType.PaneFraction );
+
+ _fontSpec = new FontSpec( Default.FontFamily, Default.FontSize,
+ Default.FontColor, Default.FontBold,
+ Default.FontItalic, Default.FontUnderline,
+ Default.FontFillColor, Default.FontFillBrush,
+ Default.FontFillType );
+ _fontSpec.Border.IsVisible = false;
+
+ _border = new Border( Default.IsBorderVisible, Default.BorderColor, Default.BorderWidth );
+ _fill = new Fill( Default.FillColor, Default.FillBrush, Default.FillType );
+
+ _gap = Default.Gap;
+
+ _isReverse = Default.IsReverse;
+
+ _isShowLegendSymbols = Default.IsShowLegendSymbols;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The XAxis object from which to copy</param>
+ public Legend( Legend rhs )
+ {
+ _rect = rhs.Rect;
+ _position = rhs.Position;
+ _isHStack = rhs.IsHStack;
+ _isVisible = rhs.IsVisible;
+
+ _location = rhs.Location;
+ _border = rhs.Border.Clone();
+ _fill = rhs.Fill.Clone();
+
+ _fontSpec = rhs.FontSpec.Clone();
+
+ _gap = rhs._gap;
+
+ _isReverse = rhs._isReverse;
+
+ _isShowLegendSymbols = rhs._isShowLegendSymbols;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Legend Clone()
+ {
+ return new Legend( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 12;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Legend( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _position = (LegendPos)info.GetValue( "position", typeof( LegendPos ) );
+ _isHStack = info.GetBoolean( "isHStack" );
+ _isVisible = info.GetBoolean( "isVisible" );
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+ _border = (Border)info.GetValue( "border", typeof( Border ) );
+ _fontSpec = (FontSpec)info.GetValue( "fontSpec", typeof( FontSpec ) );
+ _location = (Location)info.GetValue( "location", typeof( Location ) );
+
+ _gap = info.GetSingle( "gap" );
+
+ if ( schema >= 11 )
+ _isReverse = info.GetBoolean( "isReverse" );
+
+ if ( schema >= 12 )
+ _isShowLegendSymbols = info.GetBoolean( "isShowLegendSymbols" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "position", _position );
+ info.AddValue( "isHStack", _isHStack );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "fontSpec", _fontSpec );
+ info.AddValue( "location", _location );
+
+ info.AddValue( "gap", _gap );
+ info.AddValue( "isReverse", _isReverse );
+ info.AddValue( "isShowLegendSymbols", _isShowLegendSymbols );
+ }
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Render the <see cref="Legend"/> to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphPane"/> object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ // if the legend is not visible, do nothing
+ if ( !_isVisible )
+ return;
+
+ // Fill the background with the specified color if required
+ _fill.Draw( g, _rect );
+
+ PaneList paneList = GetPaneList( pane );
+
+ float halfGap = _tmpSize / 2.0F;
+
+ // Check for bad data values
+ if ( _hStack <= 0 )
+ _hStack = 1;
+ if ( _legendItemWidth <= 0 )
+ _legendItemWidth = 100;
+ if ( _legendItemHeight <= 0 )
+ _legendItemHeight = _tmpSize;
+
+ //float gap = pane.ScaledGap( scaleFactor );
+
+ int iEntry = 0;
+ float x, y;
+
+ // Get a brush for the legend label text
+ using ( SolidBrush brushB = new SolidBrush( Color.Black ) )
+ {
+ foreach ( GraphPane tmpPane in paneList )
+ {
+ // Loop for each curve in the CurveList collection
+ //foreach ( CurveItem curve in tmpPane.CurveList )
+ int count = tmpPane.CurveList.Count;
+ for ( int i = 0; i < count; i++ )
+ {
+ CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i];
+
+ if ( curve._label._text != "" && curve._label._isVisible )
+ {
+ // Calculate the x,y (TopLeft) location of the current
+ // curve legend label
+ // assuming:
+ // charHeight/2 for the left margin, plus legendWidth for each
+ // horizontal column
+ // legendHeight is the line spacing, with no extra margin above
+
+ x = _rect.Left + halfGap / 2.0F +
+ ( iEntry % _hStack ) * _legendItemWidth;
+ y = _rect.Top + (int)( iEntry / _hStack ) * _legendItemHeight;
+
+ // Draw the legend label for the current curve
+ FontSpec tmpFont = ( curve._label._fontSpec != null ) ?
+ curve._label._fontSpec : this.FontSpec;
+
+ // This is required because, for long labels, the centering can affect the
+ // position in GDI+.
+ tmpFont.StringAlignment = StringAlignment.Near;
+
+ if ( _isShowLegendSymbols )
+ {
+ tmpFont.Draw( g, pane, curve._label._text,
+ x + 2.5F * _tmpSize, y + _legendItemHeight / 2.0F,
+ AlignH.Left, AlignV.Center, scaleFactor );
+
+ RectangleF rect = new RectangleF( x, y + _legendItemHeight / 4.0F,
+ 2 * _tmpSize, _legendItemHeight / 2.0F );
+ curve.DrawLegendKey( g, tmpPane, rect, scaleFactor );
+ }
+ else
+ {
+ if ( curve._label._fontSpec == null )
+ tmpFont.FontColor = curve.Color;
+
+ tmpFont.Draw(g, pane, curve._label._text,
+ x + 0.0F * _tmpSize, y + _legendItemHeight / 2.0F,
+ AlignH.Left, AlignV.Center, scaleFactor);
+ }
+
+ // maintain a curve count for positioning
+ iEntry++;
+ }
+ }
+ if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries )
+ break;
+ }
+
+ // Draw a border around the legend if required
+ if ( iEntry > 0 )
+ this.Border.Draw( g, pane, scaleFactor, _rect );
+ }
+ }
+
+ private float GetMaxHeight( PaneList paneList, Graphics g, float scaleFactor )
+ {
+ // Set up some scaled dimensions for calculating sizes and locations
+ float defaultCharHeight = this.FontSpec.GetHeight( scaleFactor );
+ float maxCharHeight = defaultCharHeight;
+
+ // Find the largest charHeight, just in case the curves have individual fonts defined
+ foreach ( GraphPane tmpPane in paneList )
+ {
+ foreach ( CurveItem curve in tmpPane.CurveList )
+ {
+ if ( curve._label._text != string.Empty && curve._label._isVisible )
+ {
+ float tmpHeight = defaultCharHeight;
+ if ( curve._label._fontSpec != null )
+ tmpHeight = curve._label._fontSpec.GetHeight( scaleFactor );
+
+ // Account for multiline legend entries
+ tmpHeight *= curve._label._text.Split( '\n' ).Length;
+
+ if ( tmpHeight > maxCharHeight )
+ maxCharHeight = tmpHeight;
+ }
+ }
+ }
+
+ return maxCharHeight;
+ }
+
+ /// <summary>
+ /// Determine if a mouse point is within the legend, and if so, which legend
+ /// entry (<see cref="CurveItem"/>) is nearest.
+ /// </summary>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="index">The index number of the <see cref="CurveItem"/> legend
+ /// entry that is under the mouse point. The <see cref="CurveItem"/> object is
+ /// accessible via <see cref="GraphPane.CurveList">CurveList[index]</see>.
+ /// </param>
+ /// <returns>true if the mouse point is within the <see cref="Legend"/> bounding
+ /// box, false otherwise.</returns>
+ /// <seealso cref="GraphPane.FindNearestObject"/>
+ public bool FindPoint( PointF mousePt, PaneBase pane, float scaleFactor, out int index )
+ {
+ index = -1;
+
+ if ( _rect.Contains( mousePt ) )
+ {
+ int j = (int)( ( mousePt.Y - _rect.Top ) / _legendItemHeight );
+ int i = (int)( ( mousePt.X - _rect.Left - _tmpSize / 2.0f ) / _legendItemWidth );
+ if ( i < 0 )
+ i = 0;
+ if ( i >= _hStack )
+ i = _hStack - 1;
+
+ int pos = i + j * _hStack;
+ index = 0;
+
+ PaneList paneList = GetPaneList( pane );
+
+ foreach ( GraphPane tmpPane in paneList )
+ {
+ foreach ( CurveItem curve in tmpPane.CurveList )
+ {
+ if ( curve._label._isVisible && curve._label._text != string.Empty )
+ {
+ if ( pos == 0 )
+ return true;
+ pos--;
+ }
+ index++;
+ }
+ }
+
+ return true;
+ }
+ else
+ return false;
+ }
+
+ private PaneList GetPaneList( PaneBase pane )
+ {
+ // For a single GraphPane, create a PaneList to contain it
+ // Otherwise, just use the paneList from the MasterPane
+ PaneList paneList;
+
+ if ( pane is GraphPane )
+ {
+ paneList = new PaneList();
+ paneList.Add( (GraphPane)pane );
+ }
+ else
+ paneList = ( (MasterPane)pane ).PaneList;
+
+ return paneList;
+ }
+
+ /// <summary>
+ /// Calculate the <see cref="Legend"/> rectangle (<see cref="Rect"/>),
+ /// taking into account the number of required legend
+ /// entries, and the legend drawing preferences.
+ /// </summary>
+ /// <remarks>Adjust the size of the
+ /// <see cref="Chart.Rect"/> for the parent <see cref="GraphPane"/> to accomodate the
+ /// space required by the legend.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="tChartRect">
+ /// The rectangle that contains the area bounded by the axes, in pixel units.
+ /// <seealso cref="Chart.Rect" />
+ /// </param>
+ public void CalcRect( Graphics g, PaneBase pane, float scaleFactor,
+ ref RectangleF tChartRect )
+ {
+ // Start with an empty rectangle
+ _rect = Rectangle.Empty;
+ _hStack = 1;
+ _legendItemWidth = 1;
+ _legendItemHeight = 0;
+
+ RectangleF clientRect = pane.CalcClientRect( g, scaleFactor );
+
+ // If the legend is invisible, don't do anything
+ if ( !_isVisible )
+ return;
+
+ int nCurve = 0;
+
+ PaneList paneList = GetPaneList( pane );
+ _tmpSize = GetMaxHeight( paneList, g, scaleFactor );
+
+ float halfGap = _tmpSize / 2.0F,
+ maxWidth = 0,
+ tmpWidth,
+ gapPix = _gap * _tmpSize;
+
+ foreach ( GraphPane tmpPane in paneList )
+ {
+ // Loop through each curve in the curve list
+ // Find the maximum width of the legend labels
+ //foreach ( CurveItem curve in tmpPane.CurveList )
+ //foreach ( CurveItem curve in GetIterator( tmpPane.CurveList, _isReverse ) )
+ int count = tmpPane.CurveList.Count;
+ for ( int i = 0; i < count; i++ )
+ {
+ CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i];
+ if ( curve._label._text != string.Empty && curve._label._isVisible )
+ {
+ // Calculate the width of the label save the max width
+ FontSpec tmpFont = ( curve._label._fontSpec != null ) ?
+ curve._label._fontSpec : this.FontSpec;
+
+ tmpWidth = tmpFont.GetWidth( g, curve._label._text, scaleFactor );
+
+ if ( tmpWidth > maxWidth )
+ maxWidth = tmpWidth;
+
+ // Save the maximum symbol height for line-type curves
+ if ( curve is LineItem && ( (LineItem)curve ).Symbol.Size > _legendItemHeight )
+ _legendItemHeight = ( (LineItem)curve ).Symbol.Size;
+
+ nCurve++;
+ }
+ }
+
+ if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries )
+ break;
+ }
+
+ float widthAvail;
+
+ // Is this legend horizontally stacked?
+
+ if ( _isHStack )
+ {
+ // Determine the available space for horizontal stacking
+ switch ( _position )
+ {
+ // Never stack if the legend is to the right or left
+ case LegendPos.Right:
+ case LegendPos.Left:
+ widthAvail = 0;
+ break;
+
+ // for the top & bottom, the axis border width is available
+ case LegendPos.Top:
+ case LegendPos.TopCenter:
+ case LegendPos.Bottom:
+ case LegendPos.BottomCenter:
+ widthAvail = tChartRect.Width;
+ break;
+
+ // for the top & bottom flush left, the panerect less margins is available
+ case LegendPos.TopFlushLeft:
+ case LegendPos.BottomFlushLeft:
+ widthAvail = clientRect.Width;
+ break;
+
+ // for inside the axis area or Float, use 1/2 of the axis border width
+ case LegendPos.InsideTopRight:
+ case LegendPos.InsideTopLeft:
+ case LegendPos.InsideBotRight:
+ case LegendPos.InsideBotLeft:
+ case LegendPos.Float:
+ widthAvail = tChartRect.Width / 2;
+ break;
+
+ // shouldn't ever happen
+ default:
+ widthAvail = 0;
+ break;
+ }
+
+ // width of one legend entry
+ if ( _isShowLegendSymbols )
+ _legendItemWidth = 3.0f * _tmpSize + maxWidth;
+ else
+ _legendItemWidth = 0.5f * _tmpSize + maxWidth;
+
+ // Calculate the number of columns in the legend
+ // Normally, the legend is:
+ // available width / ( max width of any entry + space for line&symbol )
+ if ( maxWidth > 0 )
+ _hStack = (int)( ( widthAvail - halfGap ) / _legendItemWidth );
+
+ // You can never have more columns than legend entries
+ if ( _hStack > nCurve )
+ _hStack = nCurve;
+
+ // a saftey check
+ if ( _hStack == 0 )
+ _hStack = 1;
+ }
+ else
+ {
+ if ( _isShowLegendSymbols )
+ _legendItemWidth = 3.0F * _tmpSize + maxWidth;
+ else
+ _legendItemWidth = 0.5F * _tmpSize + maxWidth;
+ }
+
+ // legend is:
+ // item: space line space text space
+ // width: wid 4*wid wid maxWid wid
+ // The symbol is centered on the line
+ //
+ // legend begins 3 * wid to the right of the plot rect
+ //
+ // The height of the legend is the actual height of the lines of text
+ // (nCurve * hite) plus wid on top and wid on the bottom
+
+ // total legend width
+ float totLegWidth = _hStack * _legendItemWidth;
+
+ // The total legend height
+ _legendItemHeight = _legendItemHeight * (float)scaleFactor + halfGap;
+ if ( _tmpSize > _legendItemHeight )
+ _legendItemHeight = _tmpSize;
+ float totLegHeight = (float)Math.Ceiling( (double)nCurve / (double)_hStack )
+ * _legendItemHeight;
+
+ RectangleF newRect = new RectangleF();
+
+ // Now calculate the legend rect based on the above determined parameters
+ // Also, adjust the ChartRect to reflect the space for the legend
+ if ( nCurve > 0 )
+ {
+ newRect = new RectangleF( 0, 0, totLegWidth, totLegHeight );
+
+ // The switch statement assigns the left and top edges, and adjusts the ChartRect
+ // as required. The right and bottom edges are calculated at the bottom of the switch.
+ switch ( _position )
+ {
+ case LegendPos.Right:
+ newRect.X = clientRect.Right - totLegWidth;
+ newRect.Y = tChartRect.Top;
+
+ tChartRect.Width -= totLegWidth + gapPix;
+ break;
+ case LegendPos.Top:
+ newRect.X = tChartRect.Left;
+ newRect.Y = clientRect.Top;
+
+ tChartRect.Y += totLegHeight + gapPix;
+ tChartRect.Height -= totLegHeight + gapPix;
+ break;
+ case LegendPos.TopFlushLeft:
+ newRect.X = clientRect.Left;
+ newRect.Y = clientRect.Top;
+
+ tChartRect.Y += totLegHeight + gapPix * 1.5f;
+ tChartRect.Height -= totLegHeight + gapPix * 1.5f;
+ break;
+ case LegendPos.TopCenter:
+ newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2;
+ newRect.Y = tChartRect.Top;
+
+ tChartRect.Y += totLegHeight + gapPix;
+ tChartRect.Height -= totLegHeight + gapPix;
+ break;
+ case LegendPos.Bottom:
+ newRect.X = tChartRect.Left;
+ newRect.Y = clientRect.Bottom - totLegHeight;
+
+ tChartRect.Height -= totLegHeight + gapPix;
+ break;
+ case LegendPos.BottomFlushLeft:
+ newRect.X = clientRect.Left;
+ newRect.Y = clientRect.Bottom - totLegHeight;
+
+ tChartRect.Height -= totLegHeight + gapPix;
+ break;
+ case LegendPos.BottomCenter:
+ newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2;
+ newRect.Y = clientRect.Bottom - totLegHeight;
+
+ tChartRect.Height -= totLegHeight + gapPix;
+ break;
+ case LegendPos.Left:
+ newRect.X = clientRect.Left;
+ newRect.Y = tChartRect.Top;
+
+ tChartRect.X += totLegWidth + halfGap;
+ tChartRect.Width -= totLegWidth + gapPix;
+ break;
+ case LegendPos.InsideTopRight:
+ newRect.X = tChartRect.Right - totLegWidth;
+ newRect.Y = tChartRect.Top;
+ break;
+ case LegendPos.InsideTopLeft:
+ newRect.X = tChartRect.Left;
+ newRect.Y = tChartRect.Top;
+ break;
+ case LegendPos.InsideBotRight:
+ newRect.X = tChartRect.Right - totLegWidth;
+ newRect.Y = tChartRect.Bottom - totLegHeight;
+ break;
+ case LegendPos.InsideBotLeft:
+ newRect.X = tChartRect.Left;
+ newRect.Y = tChartRect.Bottom - totLegHeight;
+ break;
+ case LegendPos.Float:
+ newRect.Location = this.Location.TransformTopLeft( pane, totLegWidth, totLegHeight );
+ break;
+ }
+ }
+
+ _rect = newRect;
+ }
+
+ // /// <summary>
+ // /// Private method to the render region that gives the iterator depending on the attribute
+ // /// </summary>
+ // /// <param name="c"></param>
+ // /// <param name="forward"></param>
+ // /// <returns></returns>
+ // private IEnumerable<CurveItem> GetIterator(CurveList c, bool forward)
+ // {
+ // return forward ? c.Forward : c.Backward;
+ // }
+
+ #endregion
+ }
+}
+
diff --git a/ZedGraph/Line.cs b/ZedGraph/Line.cs
new file mode 100644
index 0000000..d1ceb5a
--- /dev/null
+++ b/ZedGraph/Line.cs
@@ -0,0 +1,1454 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class representing all the characteristics of the Line
+ /// segments that make up a curve on the graph.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.50 $ $Date: 2007-12-30 23:27:39 $ </version>
+ [Serializable]
+ public class Line : LineBase, ICloneable, ISerializable
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores the smoothing flag for this
+ /// <see cref="Line"/>. Use the public
+ /// property <see cref="IsSmooth"/> to access this value.
+ /// </summary>
+ private bool _isSmooth;
+ /// <summary>
+ /// Private field that stores the smoothing tension
+ /// for this <see cref="Line"/>. Use the public property
+ /// <see cref="SmoothTension"/> to access this value.
+ /// </summary>
+ /// <value>A floating point value indicating the level of smoothing.
+ /// 0.0F for no smoothing, 1.0F for lots of smoothing, >1.0 for odd
+ /// smoothing.</value>
+ /// <seealso cref="IsSmooth"/>
+ /// <seealso cref="Default.IsSmooth"/>
+ /// <seealso cref="Default.SmoothTension"/>
+ private float _smoothTension;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.StepType"/> for this
+ /// <see cref="CurveItem"/>. Use the public
+ /// property <see cref="StepType"/> to access this value.
+ /// </summary>
+ private StepType _stepType;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Line"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+ /// <summary>
+ /// Private field that determines if this <see cref="Line"/> will be drawn with
+ /// optimizations enabled. Use the public
+ /// property <see cref="IsOptimizedDraw"/> to access this value.
+ /// </summary>
+ private bool _isOptimizedDraw;
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Line"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ // Default Line properties
+ /// <summary>
+ /// The default color for curves (line segments connecting the points).
+ /// This is the default value for the <see cref="LineBase.Color"/> property.
+ /// </summary>
+ public static Color Color = Color.Red;
+ /// <summary>
+ /// The default color for filling in the area under the curve
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.Red;
+ /// <summary>
+ /// The default custom brush for filling in the area under the curve
+ /// (<see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null;
+ /// <summary>
+ /// The default fill mode for the curve (<see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FillType = FillType.None;
+
+ /// <summary>
+ /// The default value for the <see cref="Line.IsSmooth"/>
+ /// property.
+ /// </summary>
+ public static bool IsSmooth = false;
+ /// <summary>
+ /// The default value for the <see cref="Line.SmoothTension"/> property.
+ /// </summary>
+ public static float SmoothTension = 0.5F;
+ /// <summary>
+ /// The default value for the <see cref="Line.IsOptimizedDraw"/> property.
+ /// </summary>
+ public static bool IsOptimizedDraw = false;
+
+ /// <summary>
+ /// Default value for the curve type property
+ /// (<see cref="Line.StepType"/>). This determines if the curve
+ /// will be drawn by directly connecting the points from the
+ /// <see cref="CurveItem.Points"/> data collection,
+ /// or if the curve will be a "stair-step" in which the points are
+ /// connected by a series of horizontal and vertical lines that
+ /// represent discrete, staticant values. Note that the values can
+ /// be forward oriented <code>ForwardStep</code> (<see cref="StepType"/>) or
+ /// rearward oriented <code>RearwardStep</code>.
+ /// That is, the points are defined at the beginning or end
+ /// of the staticant value for which they apply, respectively.
+ /// </summary>
+ /// <value><see cref="StepType"/> enum value</value>
+ public static StepType StepType = StepType.NonStep;
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a property that determines if this <see cref="Line"/>
+ /// will be drawn smooth. The "smoothness" is controlled by
+ /// the <see cref="SmoothTension"/> property.
+ /// </summary>
+ /// <value>true to smooth the line, false to just connect the dots
+ /// with linear segments</value>
+ /// <seealso cref="SmoothTension"/>
+ /// <seealso cref="Default.IsSmooth"/>
+ /// <seealso cref="Default.SmoothTension"/>
+ public bool IsSmooth
+ {
+ get { return _isSmooth; }
+ set { _isSmooth = value; }
+ }
+ /// <summary>
+ /// Gets or sets a property that determines the smoothing tension
+ /// for this <see cref="Line"/>. This property is only used if
+ /// <see cref="IsSmooth"/> is true. A tension value 0.0 will just
+ /// draw ordinary line segments like an unsmoothed line. A tension
+ /// value of 1.0 will be smooth. Values greater than 1.0 will generally
+ /// give odd results.
+ /// </summary>
+ /// <value>A floating point value indicating the level of smoothing.
+ /// 0.0F for no smoothing, 1.0F for lots of smoothing, >1.0 for odd
+ /// smoothing.</value>
+ /// <seealso cref="IsSmooth"/>
+ /// <seealso cref="Default.IsSmooth"/>
+ /// <seealso cref="Default.SmoothTension"/>
+ public float SmoothTension
+ {
+ get { return _smoothTension; }
+ set { _smoothTension = value; }
+ }
+ /// <summary>
+ /// Determines if the <see cref="CurveItem"/> will be drawn by directly connecting the
+ /// points from the <see cref="CurveItem.Points"/> data collection,
+ /// or if the curve will be a "stair-step" in which the points are
+ /// connected by a series of horizontal and vertical lines that
+ /// represent discrete, constant values. Note that the values can
+ /// be forward oriented <c>ForwardStep</c> (<see cref="ZedGraph.StepType"/>) or
+ /// rearward oriented <c>RearwardStep</c>.
+ /// That is, the points are defined at the beginning or end
+ /// of the constant value for which they apply, respectively.
+ /// The <see cref="StepType"/> property is ignored for lines
+ /// that have <see cref="IsSmooth"/> set to true.
+ /// </summary>
+ /// <value><see cref="ZedGraph.StepType"/> enum value</value>
+ /// <seealso cref="Default.StepType"/>
+ public StepType StepType
+ {
+ get { return _stepType; }
+ set { _stepType = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Line"/>.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a boolean value that determines if this <see cref="Line"/> will be drawn with
+ /// optimizations enabled.
+ /// </summary>
+ /// <remarks>
+ /// Normally, the optimizations can be used without a problem, especially if the data
+ /// are sorted. The optimizations are particularly helpful with very large datasets.
+ /// However, if the data are very discontinuous (for example, a curve that doubles back
+ /// on itself), then the optimizations can cause drawing artifacts in the form of
+ /// missing line segments. The default option for this mode is false, so you must
+ /// explicitly enable it for each <see cref="LineItem.Line">LineItem.Line</see>.
+ /// Also note that, even if the optimizations are enabled explicitly, no actual
+ /// optimization will be done for datasets of less than 1000 points.
+ /// </remarks>
+ public bool IsOptimizedDraw
+ {
+ get { return _isOptimizedDraw; }
+ set { _isOptimizedDraw = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="Line"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public Line()
+ : this( Color.Empty )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that sets the color property to the specified value, and sets
+ /// the remaining <see cref="Line"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="color">The color to assign to this new Line object</param>
+ public Line( Color color )
+ {
+ _color = color.IsEmpty ? Default.Color : color;
+ _stepType = Default.StepType;
+ _isSmooth = Default.IsSmooth;
+ _smoothTension = Default.SmoothTension;
+ _fill = new Fill( Default.FillColor, Default.FillBrush, Default.FillType );
+ _isOptimizedDraw = Default.IsOptimizedDraw;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The Line object from which to copy</param>
+ public Line( Line rhs ) : base( rhs )
+ {
+ _color = rhs._color;
+ _stepType = rhs._stepType;
+ _isSmooth = rhs._isSmooth;
+ _smoothTension = rhs._smoothTension;
+ _fill = rhs._fill.Clone();
+ _isOptimizedDraw = rhs._isOptimizedDraw;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Line Clone()
+ {
+ return new Line( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 14;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Line( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ //if ( sch >= 14 )
+ // _color = (Color) info.GetValue( "color", typeof( Color ) );
+ _stepType = (StepType)info.GetValue( "stepType", typeof( StepType ) );
+ _isSmooth = info.GetBoolean( "isSmooth" );
+ _smoothTension = info.GetSingle( "smoothTension" );
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+
+ if ( sch >= 13 )
+ _isOptimizedDraw = info.GetBoolean( "isOptimizedDraw" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema", schema );
+ //info.AddValue( "color", _color );
+ info.AddValue( "stepType", _stepType );
+ info.AddValue( "isSmooth", _isSmooth );
+ info.AddValue( "smoothTension", _smoothTension );
+ info.AddValue( "fill", _fill );
+
+ info.AddValue( "isOptimizedDraw", _isOptimizedDraw );
+ }
+
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="Line"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="LineItem"/> object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ public void Draw( Graphics g, GraphPane pane, CurveItem curve, float scaleFactor )
+ {
+ // If the line is being shown, draw it
+ if ( this.IsVisible )
+ {
+ //How to handle fill vs nofill?
+ //if ( isSelected )
+ // GraphPane.Default.SelectedLine.
+
+ SmoothingMode sModeSave = g.SmoothingMode;
+ if ( _isAntiAlias )
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ if ( curve is StickItem )
+ DrawSticks( g, pane, curve, scaleFactor );
+ else if ( this.IsSmooth || this.Fill.IsVisible )
+ DrawSmoothFilledCurve( g, pane, curve, scaleFactor );
+ else
+ DrawCurve( g, pane, curve, scaleFactor );
+
+ g.SmoothingMode = sModeSave;
+ }
+ }
+
+ /// <summary>
+ /// Render a single <see cref="Line"/> segment to the specified
+ /// <see cref="Graphics"/> device.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="x1">The x position of the starting point that defines the
+ /// line segment in screen pixel units</param>
+ /// <param name="y1">The y position of the starting point that defines the
+ /// line segment in screen pixel units</param>
+ /// <param name="x2">The x position of the ending point that defines the
+ /// line segment in screen pixel units</param>
+ /// <param name="y2">The y position of the ending point that defines the
+ /// line segment in screen pixel units</param>
+ public void DrawSegment( Graphics g, GraphPane pane, float x1, float y1,
+ float x2, float y2, float scaleFactor )
+ {
+ if ( _isVisible && !this.Color.IsEmpty )
+ {
+ using ( Pen pen = GetPen( pane, scaleFactor ) )
+ {
+ g.DrawLine( pen, x1, y1, x2, y2 );
+ }
+ }
+ }
+
+ /// <summary>
+ /// Render the <see cref="Line"/>'s as vertical sticks (from a <see cref="StickItem" />) to
+ /// the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="CurveItem"/> representing this
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DrawSticks( Graphics g, GraphPane pane, CurveItem curve, float scaleFactor )
+ {
+ Line source = this;
+ if ( curve.IsSelected )
+ source = Selection.Line;
+
+ Axis yAxis = curve.GetYAxis( pane );
+ Axis xAxis = curve.GetXAxis( pane );
+
+ float basePix = yAxis.Scale.Transform( 0.0 );
+ using ( Pen pen = source.GetPen( pane, scaleFactor ) )
+ {
+ for ( int i = 0; i < curve.Points.Count; i++ )
+ {
+ PointPair pt = curve.Points[i];
+
+ if ( pt.X != PointPair.Missing &&
+ pt.Y != PointPair.Missing &&
+ !System.Double.IsNaN( pt.X ) &&
+ !System.Double.IsNaN( pt.Y ) &&
+ !System.Double.IsInfinity( pt.X ) &&
+ !System.Double.IsInfinity( pt.Y ) &&
+ ( !xAxis._scale.IsLog || pt.X > 0.0 ) &&
+ ( !yAxis._scale.IsLog || pt.Y > 0.0 ) )
+ {
+ float pixY = yAxis.Scale.Transform( curve.IsOverrideOrdinal, i, pt.Y );
+ float pixX = xAxis.Scale.Transform( curve.IsOverrideOrdinal, i, pt.X );
+
+ if ( pixX >= pane.Chart._rect.Left && pixX <= pane.Chart._rect.Right )
+ {
+ if ( pixY > pane.Chart._rect.Bottom )
+ pixY = pane.Chart._rect.Bottom;
+ if ( pixY < pane.Chart._rect.Top )
+ pixY = pane.Chart._rect.Top;
+
+ if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
+ {
+ using ( Pen tPen = GetPen( pane, scaleFactor, pt ) )
+ g.DrawLine( tPen, pixX, pixY, pixX, basePix );
+ }
+ else
+ g.DrawLine( pen, pixX, pixY, pixX, basePix );
+
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Draw the this <see cref="CurveItem"/> to the specified <see cref="Graphics"/>
+ /// device using the specified smoothing property (<see cref="ZedGraph.Line.SmoothTension"/>).
+ /// The routine draws the line segments and the area fill (if any, see <see cref="FillType"/>;
+ /// the symbols are drawn by the <see cref="Symbol.Draw"/> method. This method
+ /// is normally only called by the Draw method of the
+ /// <see cref="CurveItem"/> object. Note that the <see cref="StepType"/> property
+ /// is ignored for smooth lines (e.g., when <see cref="ZedGraph.Line.IsSmooth"/> is true).
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ public void DrawSmoothFilledCurve( Graphics g, GraphPane pane,
+ CurveItem curve, float scaleFactor )
+ {
+ Line source = this;
+ if ( curve.IsSelected )
+ source = Selection.Line;
+
+ PointF[] arrPoints;
+ int count;
+ IPointList points = curve.Points;
+
+ if ( this.IsVisible && !this.Color.IsEmpty && points != null &&
+ BuildPointsArray( pane, curve, out arrPoints, out count ) &&
+ count > 2 )
+ {
+ float tension = _isSmooth ? _smoothTension : 0f;
+
+ // Fill the curve if needed
+ if ( this.Fill.IsVisible )
+ {
+ Axis yAxis = curve.GetYAxis( pane );
+
+ using ( GraphicsPath path = new GraphicsPath( FillMode.Winding ) )
+ {
+ path.AddCurve( arrPoints, 0, count - 2, tension );
+
+ double yMin = yAxis._scale._min < 0 ? 0.0 : yAxis._scale._min;
+ CloseCurve( pane, curve, arrPoints, count, yMin, path );
+
+ RectangleF rect = path.GetBounds();
+ using ( Brush brush = source._fill.MakeBrush( rect ) )
+ {
+ if ( pane.LineType == LineType.Stack && yAxis.Scale._min < 0 &&
+ this.IsFirstLine( pane, curve ) )
+ {
+ float zeroPix = yAxis.Scale.Transform( 0 );
+ RectangleF tRect = pane.Chart._rect;
+ tRect.Height = zeroPix - tRect.Top;
+ if ( tRect.Height > 0 )
+ {
+ Region reg = g.Clip;
+ g.SetClip( tRect );
+ g.FillPath( brush, path );
+ g.SetClip( pane.Chart._rect );
+ }
+ }
+ else
+ g.FillPath( brush, path );
+ //brush.Dispose();
+ }
+
+ // restore the zero line if needed (since the fill tends to cover it up)
+ yAxis.FixZeroLine( g, pane, scaleFactor, rect.Left, rect.Right );
+ }
+ }
+
+ // If it's a smooth curve, go ahead and render the path. Otherwise, use the
+ // standard drawcurve method just in case there are missing values.
+ if ( _isSmooth )
+ {
+ using ( Pen pen = GetPen( pane, scaleFactor ) )
+ {
+ // Stroke the curve
+ g.DrawCurve( pen, arrPoints, 0, count - 2, tension );
+
+ //pen.Dispose();
+ }
+ }
+ else
+ DrawCurve( g, pane, curve, scaleFactor );
+ }
+ }
+
+ private bool IsFirstLine( GraphPane pane, CurveItem curve )
+ {
+ CurveList curveList = pane.CurveList;
+
+ for ( int j = 0; j < curveList.Count; j++ )
+ {
+ CurveItem tCurve = curveList[j];
+
+ if ( tCurve is LineItem && tCurve.IsY2Axis == curve.IsY2Axis &&
+ tCurve.YAxisIndex == curve.YAxisIndex )
+ {
+ return tCurve == curve;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Draw the this <see cref="CurveItem"/> to the specified <see cref="Graphics"/>
+ /// device. The format (stair-step or line) of the curve is
+ /// defined by the <see cref="StepType"/> property. The routine
+ /// only draws the line segments; the symbols are drawn by the
+ /// <see cref="Symbol.Draw"/> method. This method
+ /// is normally only called by the Draw method of the
+ /// <see cref="CurveItem"/> object
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ public void DrawCurve( Graphics g, GraphPane pane,
+ CurveItem curve, float scaleFactor )
+ {
+ Line source = this;
+ if ( curve.IsSelected )
+ source = Selection.Line;
+
+ // switch to int to optimize drawing speed (per Dale-a-b)
+ int tmpX, tmpY,
+ lastX = int.MaxValue,
+ lastY = int.MaxValue;
+
+ double curX, curY, lowVal;
+ PointPair curPt, lastPt = new PointPair();
+
+ bool lastBad = true;
+ IPointList points = curve.Points;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ Axis yAxis = curve.GetYAxis( pane );
+ Axis xAxis = curve.GetXAxis( pane );
+
+ bool xIsLog = xAxis._scale.IsLog;
+ bool yIsLog = yAxis._scale.IsLog;
+
+ // switch to int to optimize drawing speed (per Dale-a-b)
+ int minX = (int)pane.Chart.Rect.Left;
+ int maxX = (int)pane.Chart.Rect.Right;
+ int minY = (int)pane.Chart.Rect.Top;
+ int maxY = (int)pane.Chart.Rect.Bottom;
+
+ using ( Pen pen = source.GetPen( pane, scaleFactor ) )
+ {
+ if ( points != null && !_color.IsEmpty && this.IsVisible )
+ {
+ //bool lastOut = false;
+ bool isOut;
+
+ bool isOptDraw = _isOptimizedDraw && points.Count > 1000;
+
+ // (Dale-a-b) we'll set an element to true when it has been drawn
+ bool[,] isPixelDrawn = null;
+
+ if ( isOptDraw )
+ isPixelDrawn = new bool[maxX + 1, maxY + 1];
+
+ // Loop over each point in the curve
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ curPt = points[i];
+ if ( pane.LineType == LineType.Stack )
+ {
+ if ( !valueHandler.GetValues( curve, i, out curX, out lowVal, out curY ) )
+ {
+ curX = PointPair.Missing;
+ curY = PointPair.Missing;
+ }
+ }
+ else
+ {
+ curX = curPt.X;
+ curY = curPt.Y;
+ }
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+ if ( curX == PointPair.Missing ||
+ curY == PointPair.Missing ||
+ System.Double.IsNaN( curX ) ||
+ System.Double.IsNaN( curY ) ||
+ System.Double.IsInfinity( curX ) ||
+ System.Double.IsInfinity( curY ) ||
+ ( xIsLog && curX <= 0.0 ) ||
+ ( yIsLog && curY <= 0.0 ) )
+ {
+ // If the point is invalid, then make a linebreak only if IsIgnoreMissing is false
+ // LastX and LastY are always the last valid point, so this works out
+ lastBad = lastBad || !pane.IsIgnoreMissing;
+ isOut = true;
+ }
+ else
+ {
+ // Transform the current point from user scale units to
+ // screen coordinates
+ tmpX = (int) xAxis.Scale.Transform( curve.IsOverrideOrdinal, i, curX );
+ tmpY = (int) yAxis.Scale.Transform( curve.IsOverrideOrdinal, i, curY );
+
+ // Maintain an array of "used" pixel locations to avoid duplicate drawing operations
+ // contributed by Dale-a-b
+ if ( isOptDraw && tmpX >= minX && tmpX <= maxX &&
+ tmpY >= minY && tmpY <= maxY ) // guard against the zoom-in case
+ {
+ if ( isPixelDrawn[tmpX, tmpY] )
+ continue;
+ isPixelDrawn[tmpX, tmpY] = true;
+ }
+
+ isOut = ( tmpX < minX && lastX < minX ) || ( tmpX > maxX && lastX > maxX ) ||
+ ( tmpY < minY && lastY < minY ) || ( tmpY > maxY && lastY > maxY );
+
+ if ( !lastBad )
+ {
+ try
+ {
+ // GDI+ plots the data wrong and/or throws an exception for
+ // outrageous coordinates, so we do a sanity check here
+ if ( lastX > 5000000 || lastX < -5000000 ||
+ lastY > 5000000 || lastY < -5000000 ||
+ tmpX > 5000000 || tmpX < -5000000 ||
+ tmpY > 5000000 || tmpY < -5000000 )
+ InterpolatePoint( g, pane, curve, lastPt, scaleFactor, pen,
+ lastX, lastY, tmpX, tmpY );
+ else if ( !isOut )
+ {
+ if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
+ {
+ using ( Pen tPen = GetPen( pane, scaleFactor, lastPt ) )
+ {
+ if ( this.StepType == StepType.NonStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( tPen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardSegment )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, lastY );
+ }
+ else
+ {
+ g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );
+ }
+ }
+ }
+ else
+ {
+ if ( this.StepType == StepType.NonStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( pen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardSegment )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ }
+ else if ( this.StepType == StepType.RearwardSegment )
+ {
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ }
+ }
+
+ }
+ catch
+ {
+ InterpolatePoint( g, pane, curve, lastPt, scaleFactor, pen,
+ lastX, lastY, tmpX, tmpY );
+ }
+
+ }
+
+ lastPt = curPt;
+ lastX = tmpX;
+ lastY = tmpY;
+ lastBad = false;
+ //lastOut = isOut;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Draw the this <see cref="CurveItem"/> to the specified <see cref="Graphics"/>
+ /// device. The format (stair-step or line) of the curve is
+ /// defined by the <see cref="StepType"/> property. The routine
+ /// only draws the line segments; the symbols are drawn by the
+ /// <see cref="Symbol.Draw"/> method. This method
+ /// is normally only called by the Draw method of the
+ /// <see cref="CurveItem"/> object
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ public void DrawCurveOriginal( Graphics g, GraphPane pane,
+ CurveItem curve, float scaleFactor )
+ {
+ Line source = this;
+ if ( curve.IsSelected )
+ source = Selection.Line;
+
+ float tmpX, tmpY,
+ lastX = float.MaxValue,
+ lastY = float.MaxValue;
+ double curX, curY, lowVal;
+ PointPair curPt, lastPt = new PointPair();
+
+ bool lastBad = true;
+ IPointList points = curve.Points;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ Axis yAxis = curve.GetYAxis( pane );
+ Axis xAxis = curve.GetXAxis( pane );
+
+ bool xIsLog = xAxis._scale.IsLog;
+ bool yIsLog = yAxis._scale.IsLog;
+
+ float minX = pane.Chart.Rect.Left;
+ float maxX = pane.Chart.Rect.Right;
+ float minY = pane.Chart.Rect.Top;
+ float maxY = pane.Chart.Rect.Bottom;
+
+ using ( Pen pen = source.GetPen( pane, scaleFactor ) )
+ {
+ if ( points != null && !_color.IsEmpty && this.IsVisible )
+ {
+ //bool lastOut = false;
+ bool isOut;
+
+ // Loop over each point in the curve
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ curPt = points[i];
+ if ( pane.LineType == LineType.Stack )
+ {
+ if ( !valueHandler.GetValues( curve, i, out curX, out lowVal, out curY ) )
+ {
+ curX = PointPair.Missing;
+ curY = PointPair.Missing;
+ }
+ }
+ else
+ {
+ curX = curPt.X;
+ curY = curPt.Y;
+ }
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+ if ( curX == PointPair.Missing ||
+ curY == PointPair.Missing ||
+ System.Double.IsNaN( curX ) ||
+ System.Double.IsNaN( curY ) ||
+ System.Double.IsInfinity( curX ) ||
+ System.Double.IsInfinity( curY ) ||
+ ( xIsLog && curX <= 0.0 ) ||
+ ( yIsLog && curY <= 0.0 ) )
+ {
+ // If the point is invalid, then make a linebreak only if IsIgnoreMissing is false
+ // LastX and LastY are always the last valid point, so this works out
+ lastBad = lastBad || !pane.IsIgnoreMissing;
+ isOut = true;
+ }
+ else
+ {
+ // Transform the current point from user scale units to
+ // screen coordinates
+ tmpX = xAxis.Scale.Transform( curve.IsOverrideOrdinal, i, curX );
+ tmpY = yAxis.Scale.Transform( curve.IsOverrideOrdinal, i, curY );
+ isOut = ( tmpX < minX && lastX < minX ) || ( tmpX > maxX && lastX > maxX ) ||
+ ( tmpY < minY && lastY < minY ) || ( tmpY > maxY && lastY > maxY );
+
+ if ( !lastBad )
+ {
+ try
+ {
+ // GDI+ plots the data wrong and/or throws an exception for
+ // outrageous coordinates, so we do a sanity check here
+ if ( lastX > 5000000 || lastX < -5000000 ||
+ lastY > 5000000 || lastY < -5000000 ||
+ tmpX > 5000000 || tmpX < -5000000 ||
+ tmpY > 5000000 || tmpY < -5000000 )
+ InterpolatePoint( g, pane, curve, lastPt, scaleFactor, pen,
+ lastX, lastY, tmpX, tmpY );
+ else if ( !isOut )
+ {
+ if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
+ {
+ using ( Pen tPen = GetPen( pane, scaleFactor, lastPt ) )
+ {
+ if ( this.StepType == StepType.NonStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( tPen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardSegment )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, lastY );
+ }
+ else
+ {
+ g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );
+ }
+ }
+ }
+ else
+ {
+ if ( this.StepType == StepType.NonStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( pen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardSegment )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ }
+ else if ( this.StepType == StepType.RearwardSegment )
+ {
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ }
+ }
+
+ }
+ catch
+ {
+ InterpolatePoint( g, pane, curve, lastPt, scaleFactor, pen,
+ lastX, lastY, tmpX, tmpY );
+ }
+
+ }
+
+ lastPt = curPt;
+ lastX = tmpX;
+ lastY = tmpY;
+ lastBad = false;
+ //lastOut = isOut;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method just handles the case where one or more of the coordinates are outrageous,
+ /// or GDI+ threw an exception. This method attempts to correct the outrageous coordinates by
+ /// interpolating them to a point (along the original line) that lies at the edge of the ChartRect
+ /// so that GDI+ will handle it properly. GDI+ will throw an exception, or just plot the data
+ /// incorrectly if the coordinates are too large (empirically, this appears to be when the
+ /// coordinate value is greater than 5,000,000 or less than -5,000,000). Although you typically
+ /// would not see coordinates like this, if you repeatedly zoom in on a ZedGraphControl, eventually
+ /// all your points will be way outside the bounds of the plot.
+ /// </summary>
+ private void InterpolatePoint( Graphics g, GraphPane pane, CurveItem curve, PointPair lastPt,
+ float scaleFactor, Pen pen, float lastX, float lastY, float tmpX, float tmpY )
+ {
+ try
+ {
+ RectangleF chartRect = pane.Chart._rect;
+ // try to interpolate values
+ bool lastIn = chartRect.Contains( lastX, lastY );
+ bool curIn = chartRect.Contains( tmpX, tmpY );
+
+ // If both points are outside the ChartRect, make a new point that is on the LastX/Y
+ // side of the ChartRect, and fall through to the code that handles lastIn == true
+ if ( !lastIn )
+ {
+ float newX, newY;
+
+ if ( Math.Abs( lastX ) > Math.Abs( lastY ) )
+ {
+ newX = lastX < 0 ? chartRect.Left : chartRect.Right;
+ newY = lastY + ( tmpY - lastY ) * ( newX - lastX ) / ( tmpX - lastX );
+ }
+ else
+ {
+ newY = lastY < 0 ? chartRect.Top : chartRect.Bottom;
+ newX = lastX + ( tmpX - lastX ) * ( newY - lastY ) / ( tmpY - lastY );
+ }
+
+ lastX = newX;
+ lastY = newY;
+ }
+
+ if ( !curIn )
+ {
+ float newX, newY;
+
+ if ( Math.Abs( tmpX ) > Math.Abs( tmpY ) )
+ {
+ newX = tmpX < 0 ? chartRect.Left : chartRect.Right;
+ newY = tmpY + ( lastY - tmpY ) * ( newX - tmpX ) / ( lastX - tmpX );
+ }
+ else
+ {
+ newY = tmpY < 0 ? chartRect.Top : chartRect.Bottom;
+ newX = tmpX + ( lastX - tmpX ) * ( newY - tmpY ) / ( lastY - tmpY );
+ }
+
+ tmpX = newX;
+ tmpY = newY;
+ }
+
+ /*
+ if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( pen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ else // non-step
+ g.DrawLine( pen, lastX, lastY, tmpX, tmpY );
+ */
+ if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
+ {
+ using ( Pen tPen = GetPen( pane, scaleFactor, lastPt ) )
+ {
+ if ( this.StepType == StepType.NonStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( tPen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( tPen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardSegment )
+ {
+ g.DrawLine( tPen, lastX, lastY, tmpX, lastY );
+ }
+ else
+ {
+ g.DrawLine( tPen, lastX, tmpY, tmpX, tmpY );
+ }
+ }
+ }
+ else
+ {
+ if ( this.StepType == StepType.NonStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ g.DrawLine( pen, tmpX, lastY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ g.DrawLine( pen, lastX, lastY, lastX, tmpY );
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ else if ( this.StepType == StepType.ForwardSegment )
+ {
+ g.DrawLine( pen, lastX, lastY, tmpX, lastY );
+ }
+ else if ( this.StepType == StepType.RearwardSegment )
+ {
+ g.DrawLine( pen, lastX, tmpY, tmpX, tmpY );
+ }
+ }
+
+ }
+
+ catch { }
+ }
+
+ /// <summary>
+ /// Build an array of <see cref="PointF"/> values (pixel coordinates) that represents
+ /// the current curve. Note that this drawing routine ignores <see cref="PointPairBase.Missing"/>
+ /// values, but it does not "break" the line to indicate values are missing.
+ /// </summary>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.</param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ /// <param name="arrPoints">An array of <see cref="PointF"/> values in pixel
+ /// coordinates representing the current curve.</param>
+ /// <param name="count">The number of points contained in the "arrPoints"
+ /// parameter.</param>
+ /// <returns>true for a successful points array build, false for data problems</returns>
+ public bool BuildPointsArray( GraphPane pane, CurveItem curve,
+ out PointF[] arrPoints, out int count )
+ {
+ arrPoints = null;
+ count = 0;
+ IPointList points = curve.Points;
+
+ if ( this.IsVisible && !this.Color.IsEmpty && points != null )
+ {
+ int index = 0;
+ float curX, curY,
+ lastX = 0,
+ lastY = 0;
+ double x, y, lowVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+
+ // Step type plots get twice as many points. Always add three points so there is
+ // room to close out the curve for area fills.
+ arrPoints = new PointF[( _stepType == ZedGraph.StepType.NonStep ? 1 : 2 ) *
+ points.Count + 1];
+
+ // Loop over all points in the curve
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ // make sure that the current point is valid
+ if ( !points[i].IsInvalid )
+ {
+ // Get the user scale values for the current point
+ // use the valueHandler only for stacked types
+ if ( pane.LineType == LineType.Stack )
+ {
+ valueHandler.GetValues( curve, i, out x, out lowVal, out y );
+ }
+ // otherwise, just access the values directly. Avoiding the valueHandler for
+ // non-stacked types is an optimization to minimize overhead in case there are
+ // a large number of points.
+ else
+ {
+ x = points[i].X;
+ y = points[i].Y;
+ }
+
+ if ( x == PointPair.Missing || y == PointPair.Missing )
+ continue;
+
+ // Transform the user scale values to pixel locations
+ Axis xAxis = curve.GetXAxis( pane );
+ curX = xAxis.Scale.Transform( curve.IsOverrideOrdinal, i, x );
+ Axis yAxis = curve.GetYAxis( pane );
+ curY = yAxis.Scale.Transform( curve.IsOverrideOrdinal, i, y );
+
+ if ( curX < -1000000 || curY < -1000000 || curX > 1000000 || curY > 1000000 )
+ continue;
+
+ // Add the pixel value pair into the points array
+ // Two points are added for step type curves
+ // ignore step-type setting for smooth curves
+ if ( _isSmooth || index == 0 || this.StepType == StepType.NonStep )
+ {
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = curY;
+ }
+ else if ( this.StepType == StepType.ForwardStep ||
+ this.StepType == StepType.ForwardSegment )
+ {
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = lastY;
+ index++;
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = curY;
+ }
+ else if ( this.StepType == StepType.RearwardStep ||
+ this.StepType == StepType.RearwardSegment )
+ {
+ arrPoints[index].X = lastX;
+ arrPoints[index].Y = curY;
+ index++;
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = curY;
+ }
+
+ lastX = curX;
+ lastY = curY;
+ index++;
+
+ }
+
+ }
+
+ // Make sure there is at least one valid point
+ if ( index == 0 )
+ return false;
+
+ // Add an extra point at the end, since the smoothing algorithm requires it
+ arrPoints[index] = arrPoints[index - 1];
+ index++;
+
+ count = index;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Build an array of <see cref="PointF"/> values (pixel coordinates) that represents
+ /// the low values for the current curve.
+ /// </summary>
+ /// <remarks>Note that this drawing routine ignores <see cref="PointPairBase.Missing"/>
+ /// values, but it does not "break" the line to indicate values are missing.
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.</param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ /// <param name="arrPoints">An array of <see cref="PointF"/> values in pixel
+ /// coordinates representing the current curve.</param>
+ /// <param name="count">The number of points contained in the "arrPoints"
+ /// parameter.</param>
+ /// <returns>true for a successful points array build, false for data problems</returns>
+ public bool BuildLowPointsArray( GraphPane pane, CurveItem curve,
+ out PointF[] arrPoints, out int count )
+ {
+ arrPoints = null;
+ count = 0;
+ IPointList points = curve.Points;
+
+ if ( this.IsVisible && !this.Color.IsEmpty && points != null )
+ {
+ int index = 0;
+ float curX, curY,
+ lastX = 0,
+ lastY = 0;
+ double x, y, hiVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+
+ // Step type plots get twice as many points. Always add three points so there is
+ // room to close out the curve for area fills.
+ arrPoints = new PointF[( _stepType == ZedGraph.StepType.NonStep ? 1 : 2 ) *
+ ( pane.LineType == LineType.Stack ? 2 : 1 ) *
+ points.Count + 1];
+
+ // Loop backwards over all points in the curve
+ // In this case an array of points was already built forward by BuildPointsArray().
+ // This time we build backwards to complete a loop around the area between two curves.
+ for ( int i = points.Count - 1; i >= 0; i-- )
+ {
+ // Make sure the current point is valid
+ if ( !points[i].IsInvalid )
+ {
+ // Get the user scale values for the current point
+ valueHandler.GetValues( curve, i, out x, out y, out hiVal );
+
+ if ( x == PointPair.Missing || y == PointPair.Missing )
+ continue;
+
+ // Transform the user scale values to pixel locations
+ Axis xAxis = curve.GetXAxis( pane );
+ curX = xAxis.Scale.Transform( curve.IsOverrideOrdinal, i, x );
+ Axis yAxis = curve.GetYAxis( pane );
+ curY = yAxis.Scale.Transform( curve.IsOverrideOrdinal, i, y );
+
+ // Add the pixel value pair into the points array
+ // Two points are added for step type curves
+ // ignore step-type setting for smooth curves
+ if ( _isSmooth || index == 0 || this.StepType == StepType.NonStep )
+ {
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = curY;
+ }
+ else if ( this.StepType == StepType.ForwardStep )
+ {
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = lastY;
+ index++;
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = curY;
+ }
+ else if ( this.StepType == StepType.RearwardStep )
+ {
+ arrPoints[index].X = lastX;
+ arrPoints[index].Y = curY;
+ index++;
+ arrPoints[index].X = curX;
+ arrPoints[index].Y = curY;
+ }
+
+ lastX = curX;
+ lastY = curY;
+ index++;
+
+ }
+
+ }
+
+ // Make sure there is at least one valid point
+ if ( index == 0 )
+ return false;
+
+ // Add an extra point at the end, since the smoothing algorithm requires it
+ arrPoints[index] = arrPoints[index - 1];
+ index++;
+
+ count = index;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Close off a <see cref="GraphicsPath"/> that defines a curve
+ /// </summary>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.</param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ /// <param name="arrPoints">An array of <see cref="PointF"/> values in screen pixel
+ /// coordinates representing the current curve.</param>
+ /// <param name="count">The number of points contained in the "arrPoints"
+ /// parameter.</param>
+ /// <param name="yMin">The Y axis value location where the X axis crosses.</param>
+ /// <param name="path">The <see cref="GraphicsPath"/> class that represents the curve.</param>
+ public void CloseCurve( GraphPane pane, CurveItem curve, PointF[] arrPoints,
+ int count, double yMin, GraphicsPath path )
+ {
+ // For non-stacked lines, the fill area is just the area between the curve and the X axis
+ if ( pane.LineType != LineType.Stack )
+ {
+ // Determine the current value for the bottom of the curve (usually the Y value where
+ // the X axis crosses)
+ float yBase;
+ Axis yAxis = curve.GetYAxis( pane );
+ yBase = yAxis.Scale.Transform( yMin );
+
+ // Add three points to the path to move from the end of the curve (as defined by
+ // arrPoints) to the X axis, from there to the start of the curve at the X axis,
+ // and from there back up to the beginning of the curve.
+ path.AddLine( arrPoints[count - 1].X, arrPoints[count - 1].Y, arrPoints[count - 1].X, yBase );
+ path.AddLine( arrPoints[count - 1].X, yBase, arrPoints[0].X, yBase );
+ path.AddLine( arrPoints[0].X, yBase, arrPoints[0].X, arrPoints[0].Y );
+ }
+ // For stacked line types, the fill area is the area between this curve and the curve below it
+ else
+ {
+ PointF[] arrPoints2;
+ int count2;
+
+ float tension = _isSmooth ? _smoothTension : 0f;
+
+ // Find the next lower curve in the curveList that is also a LineItem type, and use
+ // its smoothing properties for the lower side of the filled area.
+ int index = pane.CurveList.IndexOf( curve );
+ if ( index > 0 )
+ {
+ CurveItem tmpCurve;
+ for ( int i = index - 1; i >= 0; i-- )
+ {
+ tmpCurve = pane.CurveList[i];
+ if ( tmpCurve is LineItem )
+ {
+ tension = ( (LineItem)tmpCurve ).Line.IsSmooth ? ( (LineItem)tmpCurve ).Line.SmoothTension : 0f;
+ break;
+ }
+ }
+ }
+
+ // Build another points array consisting of the low points (which are actually the points for
+ // the curve below the current curve)
+ BuildLowPointsArray( pane, curve, out arrPoints2, out count2 );
+
+ // Add the new points to the GraphicsPath
+ path.AddCurve( arrPoints2, 0, count2 - 2, tension );
+ }
+
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/LineBase.cs b/ZedGraph/LineBase.cs
new file mode 100644
index 0000000..95db60e
--- /dev/null
+++ b/ZedGraph/LineBase.cs
@@ -0,0 +1,473 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2007 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that handles the basic attributes of a line segment.
+ /// </summary>
+ /// <remarks>
+ /// This is the base class for <see cref="Line" /> and <see cref="Border" /> classes.
+ /// </remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.2 $ $Date: 2007-03-17 18:43:44 $ </version>
+ [Serializable]
+ public class LineBase : ICloneable, ISerializable
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores the pen width for this line.
+ /// Use the public property <see cref="Width"/> to access this value.
+ /// </summary>
+ internal float _width;
+ /// <summary>
+ /// Private field that stores the <see cref="DashStyle"/> for this
+ /// line. Use the public
+ /// property <see cref="Style"/> to access this value.
+ /// </summary>
+ internal DashStyle _style;
+ /// <summary>
+ /// private field that stores the "Dash On" length for drawing the line. Use the
+ /// public property <see cref="DashOn" /> to access this value.
+ /// </summary>
+ internal float _dashOn;
+ /// <summary>
+ /// private field that stores the "Dash Off" length for drawing the line. Use the
+ /// public property <see cref="DashOff" /> to access this value.
+ /// </summary>
+ internal float _dashOff;
+
+ /// <summary>
+ /// Private field that stores the visibility of this line. Use the public
+ /// property <see cref="IsVisible"/> to access this value.
+ /// </summary>
+ internal bool _isVisible;
+
+ /// <summary>
+ /// private field that determines if the line is drawn using
+ /// Anti-Aliasing capabilities from the <see cref="Graphics" /> class.
+ /// Use the public property <see cref="IsAntiAlias" /> to access
+ /// this value.
+ /// </summary>
+ internal bool _isAntiAlias;
+ /// <summary>
+ /// Private field that stores the color of this line. Use the public
+ /// property <see cref="Color"/> to access this value. If this value is
+ /// false, the line will not be shown (but the <see cref="Symbol"/> may
+ /// still be shown).
+ /// </summary>
+ internal Color _color;
+
+ /// <summary>
+ /// Internal field that stores a custom <see cref="Fill" /> class. This
+ /// fill is used strictly for <see cref="FillType.GradientByX" />,
+ /// <see cref="FillType.GradientByY" />, <see cref="FillType.GradientByZ" />,
+ /// and <see cref="FillType.GradientByColorValue" /> calculations to determine
+ /// the color of the line.
+ /// </summary>
+ internal Fill _gradientFill;
+
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="LineBase"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default mode for displaying line segments (<see cref="LineBase.IsVisible"/>
+ /// property). True to show the line segments, false to hide them.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// The default width for line segments (<see cref="LineBase.Width"/> property).
+ /// Units are points (1/72 inch).
+ /// </summary>
+ public static float Width = 1;
+ /// <summary>
+ /// The default value for the <see cref="LineBase.IsAntiAlias"/>
+ /// property.
+ /// </summary>
+ public static bool IsAntiAlias = false;
+
+ /// <summary>
+ /// The default drawing style for line segments (<see cref="LineBase.Style"/> property).
+ /// This is defined with the <see cref="DashStyle"/> enumeration.
+ /// </summary>
+ public static DashStyle Style = DashStyle.Solid;
+ /// <summary>
+ /// The default "dash on" size for drawing the line
+ /// (<see cref="LineBase.DashOn"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float DashOn = 1.0F;
+ /// <summary>
+ /// The default "dash off" size for drawing the the line
+ /// (<see cref="LineBase.DashOff"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float DashOff = 1.0F;
+
+ /// <summary>
+ /// The default color for the line.
+ /// This is the default value for the <see cref="LineBase.Color"/> property.
+ /// </summary>
+ public static Color Color = Color.Black;
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// The color of the <see cref="Line"/>. Note that this color value can be
+ /// overridden if the <see cref="Fill.Type">GradientFill.Type</see> is one of the
+ /// <see cref="FillType.GradientByX" />,
+ /// <see cref="FillType.GradientByY" />, <see cref="FillType.GradientByZ" />,
+ /// and <see cref="FillType.GradientByColorValue" /> types.
+ /// </summary>
+ /// <seealso cref="GradientFill"/>
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; }
+ }
+ /// <summary>
+ /// The style of the <see cref="Line"/>, defined as a <see cref="DashStyle"/> enum.
+ /// This allows the line to be solid, dashed, or dotted.
+ /// </summary>
+ /// <seealso cref="Default.Style"/>
+ /// <seealso cref="DashOn" />
+ /// <seealso cref="DashOff" />
+ public DashStyle Style
+ {
+ get { return _style; }
+ set { _style = value; }
+ }
+
+ /// <summary>
+ /// The "Dash On" mode for drawing the line.
+ /// </summary>
+ /// <remarks>
+ /// This is the distance, in points (1/72 inch), of the dash segments that make up
+ /// the dashed grid lines. This setting is only valid if
+ /// <see cref="Style" /> is set to <see cref="DashStyle.Custom" />.
+ /// </remarks>
+ /// <value>The dash on length is defined in points (1/72 inch)</value>
+ /// <seealso cref="DashOff"/>
+ /// <seealso cref="IsVisible"/>
+ /// <seealso cref="Default.DashOn"/>.
+ public float DashOn
+ {
+ get { return _dashOn; }
+ set { _dashOn = value; }
+ }
+ /// <summary>
+ /// The "Dash Off" mode for drawing the line.
+ /// </summary>
+ /// <remarks>
+ /// This is the distance, in points (1/72 inch), of the spaces between the dash
+ /// segments that make up the dashed grid lines. This setting is only valid if
+ /// <see cref="Style" /> is set to <see cref="DashStyle.Custom" />.
+ /// </remarks>
+ /// <value>The dash off length is defined in points (1/72 inch)</value>
+ /// <seealso cref="DashOn"/>
+ /// <seealso cref="IsVisible"/>
+ /// <seealso cref="Default.DashOff"/>.
+ public float DashOff
+ {
+ get { return _dashOff; }
+ set { _dashOff = value; }
+ }
+
+ /// <summary>
+ /// The pen width used to draw the <see cref="Line"/>, in points (1/72 inch)
+ /// </summary>
+ /// <seealso cref="Default.Width"/>
+ public float Width
+ {
+ get { return _width; }
+ set { _width = value; }
+ }
+ /// <summary>
+ /// Gets or sets a property that shows or hides the <see cref="Line"/>.
+ /// </summary>
+ /// <value>true to show the line, false to hide it</value>
+ /// <seealso cref="Default.IsVisible"/>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines if the lines are drawn using
+ /// Anti-Aliasing capabilities from the <see cref="Graphics" /> class.
+ /// </summary>
+ /// <remarks>
+ /// If this value is set to true, then the <see cref="Graphics.SmoothingMode" />
+ /// property will be set to <see cref="SmoothingMode.HighQuality" /> only while
+ /// this <see cref="Line" /> is drawn. A value of false will leave the value of
+ /// <see cref="Graphics.SmoothingMode" /> unchanged.
+ /// </remarks>
+ public bool IsAntiAlias
+ {
+ get { return _isAntiAlias; }
+ set { _isAntiAlias = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a custom <see cref="Fill" /> class.
+ /// </summary>
+ /// <remarks>This fill is used strictly for <see cref="FillType.GradientByX" />,
+ /// <see cref="FillType.GradientByY" />, <see cref="FillType.GradientByZ" />,
+ /// and <see cref="FillType.GradientByColorValue" /> calculations to determine
+ /// the color of the line. It overrides the <see cref="Color" /> property if
+ /// one of the above <see cref="FillType" /> values are selected.
+ /// </remarks>
+ /// <seealso cref="Color"/>
+ public Fill GradientFill
+ {
+ get { return _gradientFill; }
+ set { _gradientFill = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="LineBase"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public LineBase()
+ : this( Color.Empty )
+ {
+ }
+
+ /// <summary>
+ /// Constructor that sets the color property to the specified value, and sets
+ /// the remaining <see cref="LineBase"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="color">The color to assign to this new Line object</param>
+ public LineBase( Color color )
+ {
+ _width = Default.Width;
+ _style = Default.Style;
+ _dashOn = Default.DashOn;
+ _dashOff = Default.DashOff;
+ _isVisible = Default.IsVisible;
+ _color = color.IsEmpty ? Default.Color : color;
+ _isAntiAlias = Default.IsAntiAlias;
+ _gradientFill = new Fill( Color.Red, Color.White );
+ _gradientFill.Type = FillType.None;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The LineBase object from which to copy</param>
+ public LineBase( LineBase rhs )
+ {
+ _width = rhs._width;
+ _style = rhs._style;
+ _dashOn = rhs._dashOn;
+ _dashOff = rhs._dashOff;
+
+ _isVisible = rhs._isVisible;
+ _color = rhs._color;
+
+ _isAntiAlias = rhs._isAntiAlias;
+ _gradientFill = new Fill( rhs._gradientFill );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of Clone.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method must be called with an explicit cast to ICloneable, and
+ /// that it is inherently virtual. For example:
+ /// <code>
+ /// ParentClass foo = new ChildClass();
+ /// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
+ /// </code>
+ /// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
+ /// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
+ /// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
+ /// </remarks>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
+ //return new PaneBase( this );
+ }
+
+ // /// <summary>
+ // /// Typesafe, deep-copy clone method.
+ // /// </summary>
+ // /// <returns>A new, independent copy of this class</returns>
+ //public LineBase Clone()
+ //{
+ // return new LineBase( this );
+ //}
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema0 = 12;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the
+ /// serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains
+ /// the serialized data
+ /// </param>
+ protected LineBase( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema0" );
+
+ _width = info.GetSingle( "width" );
+ _style = (DashStyle)info.GetValue( "style", typeof( DashStyle ) );
+ _dashOn = info.GetSingle( "dashOn" );
+ _dashOff = info.GetSingle( "dashOff" );
+ _isVisible = info.GetBoolean( "isVisible" );
+ _isAntiAlias = info.GetBoolean( "isAntiAlias" );
+ _color = (Color)info.GetValue( "color", typeof( Color ) );
+ _gradientFill = (Fill)info.GetValue( "gradientFill", typeof( Fill ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize
+ /// the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the
+ /// serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the
+ /// serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema0", schema0 );
+
+ info.AddValue( "width", _width );
+ info.AddValue( "style", _style );
+ info.AddValue( "dashOn", _dashOn );
+ info.AddValue( "dashOff", _dashOff );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "isAntiAlias", _isAntiAlias );
+ info.AddValue( "color", _color );
+ info.AddValue( "gradientFill", _gradientFill );
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Create a <see cref="Pen" /> object based on the properties of this
+ /// <see cref="LineBase" />.
+ /// </summary>
+ /// <param name="pane">The owner <see cref="GraphPane" /> of this
+ /// <see cref="LineBase" />.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>A <see cref="Pen" /> object with the properties of this <see cref="LineBase" />
+ /// </returns>
+ public Pen GetPen( PaneBase pane, float scaleFactor )
+ {
+ return GetPen( pane, scaleFactor, null );
+ }
+
+ /// <summary>
+ /// Create a <see cref="Pen" /> object based on the properties of this
+ /// <see cref="LineBase" />.
+ /// </summary>
+ /// <param name="pane">The owner <see cref="GraphPane" /> of this
+ /// <see cref="LineBase" />.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="dataValue">The data value to be used for a value-based
+ /// color gradient. This is only applicable if <see cref="Fill.Type">GradientFill.Type</see>
+ /// is one of <see cref="FillType.GradientByX"/>,
+ /// <see cref="FillType.GradientByY"/>, <see cref="FillType.GradientByZ"/>,
+ /// or <see cref="FillType.GradientByColorValue" />.
+ /// </param>
+ /// <returns>A <see cref="Pen" /> object with the properties of this <see cref="LineBase" />
+ /// </returns>
+ public Pen GetPen( PaneBase pane, float scaleFactor, PointPair dataValue )
+ {
+ Color color = _color;
+ if ( _gradientFill.IsGradientValueType )
+ color = _gradientFill.GetGradientColor( dataValue );
+
+ Pen pen = new Pen( color,
+ pane.ScaledPenWidth( _width, scaleFactor ) );
+
+ pen.DashStyle = _style;
+
+ if ( _style == DashStyle.Custom )
+ {
+ if ( _dashOff > 1e-10 && _dashOn > 1e-10 )
+ {
+ pen.DashStyle = DashStyle.Custom;
+ float[] pattern = new float[2];
+ pattern[0] = _dashOn;
+ pattern[1] = _dashOff;
+ pen.DashPattern = pattern;
+ }
+ else
+ pen.DashStyle = DashStyle.Solid;
+ }
+
+ return pen;
+ }
+
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/LineItem.cs b/ZedGraph/LineItem.cs
new file mode 100644
index 0000000..dad7be7
--- /dev/null
+++ b/ZedGraph/LineItem.cs
@@ -0,0 +1,393 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates a curve type that is displayed as a line and/or a set of
+ /// symbols at each point.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.22 $ $Date: 2007-08-10 16:22:54 $ </version>
+ [Serializable]
+ public class LineItem : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="ZedGraph.Symbol"/>
+ /// class defined for this <see cref="LineItem"/>. Use the public
+ /// property <see cref="Symbol"/> to access this value.
+ /// </summary>
+ protected Symbol _symbol;
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="ZedGraph.Line"/>
+ /// class defined for this <see cref="LineItem"/>. Use the public
+ /// property <see cref="Line"/> to access this value.
+ /// </summary>
+ protected Line _line;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Symbol"/> class instance defined
+ /// for this <see cref="LineItem"/>.
+ /// </summary>
+ public Symbol Symbol
+ {
+ get { return _symbol; }
+ set { _symbol = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Line"/> class instance defined
+ /// for this <see cref="LineItem"/>.
+ /// </summary>
+ public Line Line
+ {
+ get { return _line; }
+ set { _line = value; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return true;
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="LineItem"/>, specifying only the legend <see cref="CurveItem.Label" />.
+ /// </summary>
+ /// <param name="label">The _label that will appear in the legend.</param>
+ public LineItem( string label ) : base( label )
+ {
+ _symbol = new Symbol();
+ _line = new Line();
+ }
+
+ /// <summary>
+ /// Create a new <see cref="LineItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The _label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ /// <param name="symbolType">A <see cref="SymbolType"/> enum specifying the
+ /// type of symbol to use for this <see cref="LineItem"/>. Use <see cref="SymbolType.None"/>
+ /// to hide the symbols.</param>
+ /// <param name="lineWidth">The width (in points) to be used for the <see cref="Line"/>. This
+ /// width is scaled based on <see cref="PaneBase.CalcScaleFactor"/>. Use a value of zero to
+ /// hide the line (see <see cref="ZedGraph.LineBase.IsVisible"/>).</param>
+ public LineItem( string label, double[] x, double[] y, Color color, SymbolType symbolType, float lineWidth )
+ : this( label, new PointPairList( x, y ), color, symbolType, lineWidth )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="LineItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The _label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ /// <param name="symbolType">A <see cref="SymbolType"/> enum specifying the
+ /// type of symbol to use for this <see cref="LineItem"/>. Use <see cref="SymbolType.None"/>
+ /// to hide the symbols.</param>
+ public LineItem( string label, double[] x, double[] y, Color color, SymbolType symbolType )
+ : this( label, new PointPairList( x, y ), color, symbolType )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="LineItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The _label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ /// <param name="symbolType">A <see cref="SymbolType"/> enum specifying the
+ /// type of symbol to use for this <see cref="LineItem"/>. Use <see cref="SymbolType.None"/>
+ /// to hide the symbols.</param>
+ /// <param name="lineWidth">The width (in points) to be used for the <see cref="Line"/>. This
+ /// width is scaled based on <see cref="PaneBase.CalcScaleFactor"/>. Use a value of zero to
+ /// hide the line (see <see cref="ZedGraph.LineBase.IsVisible"/>).</param>
+ public LineItem( string label, IPointList points, Color color, SymbolType symbolType, float lineWidth )
+ : base( label, points )
+ {
+ _line = new Line( color );
+ if ( lineWidth == 0 )
+ _line.IsVisible = false;
+ else
+ _line.Width = lineWidth;
+
+ _symbol = new Symbol( symbolType, color );
+ }
+
+ /// <summary>
+ /// Create a new <see cref="LineItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The _label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ /// <param name="symbolType">A <see cref="SymbolType"/> enum specifying the
+ /// type of symbol to use for this <see cref="LineItem"/>. Use <see cref="SymbolType.None"/>
+ /// to hide the symbols.</param>
+ public LineItem( string label, IPointList points, Color color, SymbolType symbolType )
+ : this( label, points, color, symbolType, ZedGraph.LineBase.Default.Width )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="LineItem"/> object from which to copy</param>
+ public LineItem( LineItem rhs ) : base( rhs )
+ {
+ _symbol = new Symbol( rhs.Symbol );
+ _line = new Line( rhs.Line );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public LineItem Clone()
+ {
+ return new LineItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected LineItem( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _symbol = (Symbol) info.GetValue( "symbol", typeof(Symbol) );
+ _line = (Line) info.GetValue( "line", typeof(Line) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "symbol", _symbol );
+ info.AddValue( "line", _line );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Do all rendering associated with this <see cref="LineItem"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">The ordinal position of the current <see cref="Bar"/>
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( _isVisible )
+ {
+ Line.Draw( g, pane, this, scaleFactor );
+
+ Symbol.Draw( g, pane, this, scaleFactor, IsSelected );
+ }
+ }
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="LineItem"/> at the specified location
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ // Draw a sample curve to the left of the label text
+ int xMid = (int)( rect.Left + rect.Width / 2.0F );
+ int yMid = (int) (rect.Top + rect.Height / 2.0F);
+ //RectangleF rect2 = rect;
+ //rect2.Y = yMid;
+ //rect2.Height = rect.Height / 2.0f;
+
+ _line.Fill.Draw( g, rect );
+
+ _line.DrawSegment( g, pane, rect.Left, yMid, rect.Right, yMid, scaleFactor );
+
+ // Draw a sample symbol to the left of the label text
+ _symbol.DrawSymbol( g, pane, xMid, yMid, scaleFactor, false, null );
+
+ }
+
+ /// <summary>
+ /// Loads some pseudo unique colors/symbols into this LineItem. This
+ /// is mainly useful for differentiating a set of new LineItems without
+ /// having to pick your own colors/symbols.
+ /// <seealso cref="CurveItem.MakeUnique( ColorSymbolRotator )"/>
+ /// </summary>
+ /// <param name="rotator">
+ /// The <see cref="ColorSymbolRotator"/> that is used to pick the color
+ /// and symbol for this method call.
+ /// </param>
+ override public void MakeUnique( ColorSymbolRotator rotator )
+ {
+ this.Color = rotator.NextColor;
+ this.Symbol.Type = rotator.NextSymbol;
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ override public bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = string.Empty;
+
+ if ( i < 0 || i >= _points.Count )
+ return false;
+
+ PointPair pt = _points[i];
+ if ( pt.IsInvalid )
+ return false;
+
+ double x, y, z;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ valueHandler.GetValues( this, i, out x, out z, out y );
+
+ Axis yAxis = GetYAxis( pane );
+ Axis xAxis = GetXAxis( pane );
+
+ PointF pixPt = new PointF( xAxis.Scale.Transform( _isOverrideOrdinal, i, x ),
+ yAxis.Scale.Transform( _isOverrideOrdinal, i, y ) );
+
+ if ( !pane.Chart.Rect.Contains( pixPt ) )
+ return false;
+
+ float halfSize = _symbol.Size * pane.CalcScaleFactor();
+
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixPt.X - halfSize, pixPt.Y - halfSize,
+ pixPt.X + halfSize, pixPt.Y + halfSize );
+
+ return true;
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/LineObj.cs b/ZedGraph/LineObj.cs
new file mode 100644
index 0000000..1fc30ee
--- /dev/null
+++ b/ZedGraph/LineObj.cs
@@ -0,0 +1,337 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents a line segment object on the graph. A list of
+ /// GraphObj objects is maintained by the <see cref="GraphObjList"/> collection class.
+ /// </summary>
+ /// <remarks>
+ /// This should not be confused with the <see cref="LineItem" /> class, which represents
+ /// a set of points plotted together as a "curve". The <see cref="LineObj" /> class is
+ /// a single line segment, drawn as a "decoration" on the chart.</remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-01-25 07:56:09 $ </version>
+ [Serializable]
+ public class LineObj : GraphObj, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// protected field that maintains the attributes of the line using an
+ /// instance of the <see cref="LineBase" /> class.
+ /// </summary>
+ protected LineBase _line;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// A <see cref="LineBase" /> class that contains the attributes for drawing this
+ /// <see cref="LineObj" />.
+ /// </summary>
+ public LineBase Line
+ {
+ get { return _line; }
+ set { _line = value; }
+ }
+
+ #endregion
+
+
+ #region Constructors
+
+ /// <overloads>Constructors for the <see cref="LineObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the position, color, and size of the
+ /// <see cref="LineObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="color">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the arrow</param>
+ /// <param name="x1">The x position of the starting point that defines the
+ /// line. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y1">The y position of the starting point that defines the
+ /// line. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="x2">The x position of the ending point that defines the
+ /// line. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y2">The y position of the ending point that defines the
+ /// line. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ public LineObj( Color color, double x1, double y1, double x2, double y2 )
+ : base( x1, y1, x2 - x1, y2 - y1 )
+ {
+ _line = new LineBase( color );
+ this.Location.AlignH = AlignH.Left;
+ this.Location.AlignV = AlignV.Top;
+ }
+
+ /// <summary>
+ /// A constructor that allows only the position of the
+ /// line to be pre-specified. All other properties are set to
+ /// default values
+ /// </summary>
+ /// <param name="x1">The x position of the starting point that defines the
+ /// <see cref="LineObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y1">The y position of the starting point that defines the
+ /// <see cref="LineObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="x2">The x position of the ending point that defines the
+ /// <see cref="LineObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ /// <param name="y2">The y position of the ending point that defines the
+ /// <see cref="LineObj"/>. The units of this position are specified by the
+ /// <see cref="Location.CoordinateFrame"/> property.</param>
+ public LineObj( double x1, double y1, double x2, double y2 )
+ : this( LineBase.Default.Color, x1, y1, x2, y2 )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor -- places the <see cref="LineObj"/> at location
+ /// (0,0) to (1,1). All other values are defaulted.
+ /// </summary>
+ public LineObj() : this( LineBase.Default.Color, 0, 0, 1, 1 )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="LineObj"/> object from which to copy</param>
+ public LineObj( LineObj rhs ) : base( rhs )
+ {
+ _line = new LineBase( rhs._line );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public LineObj Clone()
+ {
+ return new LineObj( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ // changed to 2 with addition of Style property
+ public const int schema2 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected LineObj( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _line = (LineBase)info.GetValue( "line", typeof( LineBase ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+
+ info.AddValue( "line", _line );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this object to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ // Convert the arrow coordinates from the user coordinate system
+ // to the screen coordinate system
+ PointF pix1 = this.Location.TransformTopLeft( pane );
+ PointF pix2 = this.Location.TransformBottomRight( pane );
+
+ if ( pix1.X > -10000 && pix1.X < 100000 && pix1.Y > -100000 && pix1.Y < 100000 &&
+ pix2.X > -10000 && pix2.X < 100000 && pix2.Y > -100000 && pix2.Y < 100000 )
+ {
+ // calculate the length and the angle of the arrow "vector"
+ double dy = pix2.Y - pix1.Y;
+ double dx = pix2.X - pix1.X;
+ float angle = (float)Math.Atan2( dy, dx ) * 180.0F / (float)Math.PI;
+ float length = (float)Math.Sqrt( dx * dx + dy * dy );
+
+ // Save the old transform matrix
+ Matrix transform = g.Transform;
+ // Move the coordinate system so it is located at the starting point
+ // of this arrow
+ g.TranslateTransform( pix1.X, pix1.Y );
+ // Rotate the coordinate system according to the angle of this arrow
+ // about the starting point
+ g.RotateTransform( angle );
+
+ // get a pen according to this arrow properties
+ using ( Pen pen = _line.GetPen( pane, scaleFactor ) )
+ //new Pen( _line._color, pane.ScaledPenWidth( _line._width, scaleFactor ) ) )
+ {
+ //pen.DashStyle = _style;
+
+ g.DrawLine( pen, 0, 0, length, 0 );
+ }
+
+ // Restore the transform matrix back to its original state
+ g.Transform = transform;
+ }
+ }
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="LineObj"/>.
+ /// </summary>
+ /// <remarks>The bounding box is calculated assuming a distance
+ /// of <see cref="GraphPane.Default.NearestTol"/> pixels around the arrow segment.
+ /// </remarks>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ if ( ! base.PointInBox(pt, pane, g, scaleFactor ) )
+ return false;
+
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ PointF pix = _location.TransformTopLeft( pane );
+ PointF pix2 = _location.TransformBottomRight( pane );
+
+ using ( Pen pen = new Pen( Color.Black, (float)GraphPane.Default.NearestTol * 2.0F ) )
+ {
+ using ( GraphicsPath path = new GraphicsPath() )
+ {
+ path.AddLine( pix, pix2 );
+ return path.IsOutlineVisible( pt, pen );
+ }
+ }
+ }
+
+ /// <summary>
+ /// Determines the shape type and Coords values for this GraphObj
+ /// </summary>
+ override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor,
+ out string shape, out string coords )
+ {
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ RectangleF pixRect = _location.TransformRect( pane );
+
+ Matrix matrix = new Matrix();
+ if ( pixRect.Right == 0 )
+ pixRect.Width = 1;
+ float angle = (float) Math.Atan( ( pixRect.Top - pixRect.Bottom ) /
+ ( pixRect.Left - pixRect.Right ) );
+ matrix.Rotate( angle, MatrixOrder.Prepend );
+
+ // Move the coordinate system to local coordinates
+ // of this text object (that is, at the specified
+ // x,y location)
+ matrix.Translate( -pixRect.Left, -pixRect.Top, MatrixOrder.Prepend );
+
+ PointF[] pts = new PointF[4];
+ pts[0] = new PointF( 0, 3 );
+ pts[1] = new PointF( pixRect.Width, 3 );
+ pts[2] = new PointF( pixRect.Width, -3 );
+ pts[3] = new PointF( 0, -3 );
+ matrix.TransformPoints( pts );
+
+ shape = "poly";
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0},{4:f0},{5:f0},{6:f0},{7:f0},",
+ pts[0].X, pts[0].Y, pts[1].X, pts[1].Y,
+ pts[2].X, pts[2].Y, pts[3].X, pts[3].Y );
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/LinearAsOrdinalScale.cs b/ZedGraph/LinearAsOrdinalScale.cs
new file mode 100644
index 0000000..17321a3
--- /dev/null
+++ b/ZedGraph/LinearAsOrdinalScale.cs
@@ -0,0 +1,243 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The LinearAsOrdinalScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.LinearAsOrdinal" />.
+ /// </summary>
+ /// <remarks>
+ /// LinearAsOrdinal is an ordinal axis that will have labels formatted with values from the actual data
+ /// values of the first <see cref="CurveItem" /> in the <see cref="CurveList" />.
+ /// Although the tics are labeled with real data values, the actual points will be
+ /// evenly-spaced in spite of the data values. For example, if the X values of the first curve
+ /// are 1, 5, and 100, then the tic labels will show 1, 5, and 100, but they will be equal
+ /// distance from each other.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.10 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ class LinearAsOrdinalScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public LinearAsOrdinalScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="LinearAsOrdinalScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="LinearAsOrdinalScale" /></param>
+ public LinearAsOrdinalScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new LinearAsOrdinalScale( this, owner );
+ }
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Return the <see cref="AxisType" /> for this <see cref="Scale" />, which is
+ /// <see cref="AxisType.LinearAsOrdinal" />.
+ /// </summary>
+ public override AxisType Type
+ {
+ get { return AxisType.LinearAsOrdinal; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Select a reasonable ordinal axis scale given a range of data values, with the expectation that
+ /// linear values will be displayed.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.DateAsOrdinal"/> type axes, and it
+ /// is called by the general <see cref="Scale.PickScale"/> method. For this type,
+ /// the first curve is the "master", which contains the dates to be applied.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="PickScale"/>
+ /// <seealso cref="AxisType.Ordinal"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ // First, get the date ranges from the first curve in the list
+ double xMin; // = Double.MaxValue;
+ double xMax; // = Double.MinValue;
+ double yMin; // = Double.MaxValue;
+ double yMax; // = Double.MinValue;
+ double tMin = 0;
+ double tMax = 1;
+
+ foreach ( CurveItem curve in pane.CurveList )
+ {
+ if ( ( _ownerAxis is Y2Axis && curve.IsY2Axis ) ||
+ ( _ownerAxis is YAxis && !curve.IsY2Axis ) ||
+ ( _ownerAxis is X2Axis && curve.IsX2Axis ) ||
+ ( _ownerAxis is XAxis && !curve.IsX2Axis ) )
+ {
+ curve.GetRange( out xMin, out xMax, out yMin, out yMax, false, false, pane );
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ {
+ tMin = xMin;
+ tMax = xMax;
+ }
+ else
+ {
+ tMin = yMin;
+ tMax = yMax;
+ }
+ }
+ }
+
+ double range = Math.Abs( tMax - tMin );
+
+ // Now, set the axis range based on a ordinal scale
+ base.PickScale( pane, g, scaleFactor );
+ OrdinalScale.PickScale( pane, g, scaleFactor, this );
+
+ SetScaleMag( tMin, tMax, range / Default.TargetXSteps );
+ }
+
+ /// <summary>
+ /// Make a value label for an <see cref="AxisType.LinearAsOrdinal" /> <see cref="Axis" />.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="Scale.IsLog"/>)
+ /// and text (<see cref="Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ override internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ double val;
+
+ int tmpIndex = (int) dVal - 1;
+
+ if ( pane.CurveList.Count > 0 && pane.CurveList[0].Points.Count > tmpIndex )
+ {
+ val = pane.CurveList[0].Points[tmpIndex].X;
+ double scaleMult = Math.Pow( (double) 10.0, _mag );
+ return ( val / scaleMult ).ToString( _format );
+ }
+ else
+ return string.Empty;
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected LinearAsOrdinalScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/LinearScale.cs b/ZedGraph/LinearScale.cs
new file mode 100644
index 0000000..2e2dc1b
--- /dev/null
+++ b/ZedGraph/LinearScale.cs
@@ -0,0 +1,233 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The LinearScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.Linear" />.
+ /// </summary>
+ /// <remarks>
+ /// LinearScale is the normal, default cartesian axis.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.10 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ class LinearScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public LinearScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="LinearScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="LinearScale" /></param>
+ public LinearScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new LinearScale( this, owner );
+ }
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Return the <see cref="AxisType" /> for this <see cref="Scale" />, which is
+ /// <see cref="AxisType.Linear" />.
+ /// </summary>
+ public override AxisType Type
+ {
+ get { return AxisType.Linear; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Select a reasonable linear axis scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.Linear"/> type axes, and it
+ /// is called by the general <see cref="Scale.PickScale"/> method. The scale range is chosen
+ /// based on increments of 1, 2, or 5 (because they are even divisors of 10). This
+ /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/> autorange settings.
+ /// In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/>
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values. The basic defaults for
+ /// scale selection are defined using <see cref="Scale.Default.ZeroLever"/>,
+ /// <see cref="Scale.Default.TargetXSteps"/>, and <see cref="Scale.Default.TargetYSteps"/>
+ /// from the <see cref="Scale.Default"/> default class.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="PickScale"/>
+ /// <seealso cref="AxisType.Linear"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ // Test for trivial condition of range = 0 and pick a suitable default
+ if ( _max - _min < 1.0e-30 )
+ {
+ if ( _maxAuto )
+ _max = _max + 0.2 * ( _max == 0 ? 1.0 : Math.Abs( _max ) );
+ if ( _minAuto )
+ _min = _min - 0.2 * ( _min == 0 ? 1.0 : Math.Abs( _min ) );
+ }
+
+ // This is the zero-lever test. If minVal is within the zero lever fraction
+ // of the data range, then use zero.
+
+ if ( _minAuto && _min > 0 &&
+ _min / ( _max - _min ) < Default.ZeroLever )
+ _min = 0;
+
+ // Repeat the zero-lever test for cases where the maxVal is less than zero
+ if ( _maxAuto && _max < 0 &&
+ Math.Abs( _max / ( _max - _min ) ) <
+ Default.ZeroLever )
+ _max = 0;
+
+ // Calculate the new step size
+ if ( _majorStepAuto )
+ {
+ double targetSteps = ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ?
+ Default.TargetXSteps : Default.TargetYSteps;
+
+ // Calculate the step size based on target steps
+ _majorStep = CalcStepSize( _max - _min, targetSteps );
+
+ if ( _isPreventLabelOverlap )
+ {
+ // Calculate the maximum number of labels
+ double maxLabels = (double) this.CalcMaxLabels( g, pane, scaleFactor );
+
+ if ( maxLabels < ( _max - _min ) / _majorStep )
+ _majorStep = CalcBoundedStepSize( _max - _min, maxLabels );
+ }
+ }
+
+ // Calculate the new step size
+ if ( _minorStepAuto )
+ _minorStep = CalcStepSize( _majorStep,
+ ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) ?
+ Default.TargetMinorXSteps : Default.TargetMinorYSteps );
+
+ // Calculate the scale minimum
+ if ( _minAuto )
+ _min = _min - MyMod( _min, _majorStep );
+
+ // Calculate the scale maximum
+ if ( _maxAuto )
+ _max = MyMod( _max, _majorStep ) == 0.0 ? _max :
+ _max + _majorStep - MyMod( _max, _majorStep );
+
+ SetScaleMag( _min, _max, _majorStep );
+ }
+
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected LinearScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Link.cs b/ZedGraph/Link.cs
new file mode 100644
index 0000000..3d824aa
--- /dev/null
+++ b/ZedGraph/Link.cs
@@ -0,0 +1,303 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that maintains hyperlink information for a clickable object on the graph.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.6 $ $Date: 2007-04-16 00:03:02 $ </version>
+ // /// <seealso cref="ZedGraph.Web.IsImageMap"/>
+ [Serializable]
+ public class Link : ISerializable, ICloneable
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// Internal field that stores the title string for this link.
+ /// </summary>
+ internal string _title;
+
+ /// <summary>
+ /// Internal field that stores the url string for this link
+ /// </summary>
+ internal string _url;
+
+ /// <summary>
+ /// Internal field that stores the target string for this link
+ /// </summary>
+ internal string _target;
+
+ /// <summary>
+ /// Internal field that determines if this link is "live".
+ /// </summary>
+ internal bool _isEnabled;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the title string for this link.
+ /// </summary>
+ /// <remarks>
+ /// For web controls, this title will be shown as a tooltip when the mouse
+ /// hovers over the area of the object that owns this link. Set the value to
+ /// <see cref="String.Empty" /> to have no title.
+ /// </remarks>
+ public string Title
+ {
+ get { return _title; }
+ set { _title = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the url string for this link.
+ /// </summary>
+ /// <remarks>
+ /// Set this value to <see cref="String.Empty" /> if you don't want to have
+ /// a hyperlink associated with the object to which this link belongs.
+ /// </remarks>
+ public string Url
+ {
+ get { return _url; }
+ set { _url = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the target string for this link.
+ /// </summary>
+ /// <remarks>
+ /// This value should be set to a valid target associated with the "Target"
+ /// property of an html hyperlink. Typically, this would be "_blank" to open
+ /// a new browser window, or "_self" to open in the current browser.
+ /// </remarks>
+ public string Target
+ {
+ get { return _target != string.Empty ? _target : "_self"; }
+ set { _target = value; }
+ }
+
+ /// <summary>
+ /// A tag object for use by the user. This can be used to store additional
+ /// information associated with the <see cref="Link"/>. ZedGraph does
+ /// not use this value for any purpose.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if you are going to Serialize ZedGraph data, then any type
+ /// that you store in <see cref="Tag"/> must be a serializable type (or
+ /// it will cause an exception).
+ /// </remarks>
+ public object Tag;
+
+ /// <summary>
+ /// Gets or sets a property that determines if this link is active. True to have
+ /// a clickable link, false to ignore the link.
+ /// </summary>
+ public bool IsEnabled
+ {
+ get { return _isEnabled; }
+ set { _isEnabled = value; }
+ }
+
+ /// <summary>
+ /// Gets a value that indicates if this <see cref="Link" /> is enabled
+ /// (see <see cref="IsEnabled" />), and that either the
+ /// <see cref="Url" /> or the <see cref="Title" /> is non-null.
+ /// </summary>
+ public bool IsActive
+ {
+ get { return _isEnabled && ( _url != null || _title != null ); }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor. Set all properties to string.Empty, or null.
+ /// </summary>
+ public Link()
+ {
+ _title = string.Empty;
+ _url = string.Empty;
+ _target = string.Empty;
+ this.Tag = null;
+ _isEnabled = false;
+ }
+
+ /// <summary>
+ /// Construct a Link instance from a specified title, url, and target.
+ /// </summary>
+ /// <param name="title">The title for the link (which shows up in the tooltip).</param>
+ /// <param name="url">The URL destination for the link.</param>
+ /// <param name="target">The target for the link (typically "_blank" or "_self").</param>
+ public Link( string title, string url, string target )
+ {
+ _title = title;
+ _url = url;
+ _target = target;
+ Tag = null;
+ _isEnabled = true;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="Link"/> object from which to copy</param>
+ public Link( Link rhs )
+ {
+ // Copy value types
+ _title = rhs._title;
+ _url = rhs._url;
+ _target = rhs._target;
+ _isEnabled = false;
+
+ // copy reference types by cloning
+ if ( rhs.Tag is ICloneable )
+ this.Tag = ((ICloneable) rhs.Tag).Clone();
+ else
+ this.Tag = rhs.Tag;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Link Clone()
+ {
+ return new Link( this );
+ }
+
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Create a URL for a <see cref="CurveItem" /> that includes the index of the
+ /// point that was selected.
+ /// </summary>
+ /// <remarks>
+ /// An "index" parameter is added to the <see cref="Url" /> property for this
+ /// link to indicate which point was selected. Further, if the
+ /// X or Y axes that correspond to this <see cref="CurveItem" /> are of
+ /// <see cref="AxisType.Text" />, then an
+ /// additional parameter will be added containing the text value that
+ /// corresponds to the <paramref name="index" /> of the selected point.
+ /// The <see cref="XAxis" /> text parameter will be labeled "xtext", and
+ /// the <see cref="YAxis" /> text parameter will be labeled "ytext".
+ /// </remarks>
+ /// <param name="index">The zero-based index of the selected point</param>
+ /// <param name="pane">The <see cref="GraphPane" /> of interest</param>
+ /// <param name="curve">The <see cref="CurveItem" /> for which to
+ /// make the url string.</param>
+ /// <returns>A string containing the url with an index parameter added.</returns>
+ public virtual string MakeCurveItemUrl( GraphPane pane, CurveItem curve, int index )
+ {
+ string url = _url;
+
+ if ( url.IndexOf( '?' ) >= 0 )
+ url += "&index=" + index.ToString();
+ else
+ url += "?index=" + index.ToString();
+
+ Axis xAxis = curve.GetXAxis( pane );
+ if ( xAxis.Type == AxisType.Text && index >= 0 &&
+ xAxis.Scale.TextLabels != null &&
+ index <= xAxis.Scale.TextLabels.Length )
+ url += "&xtext=" + xAxis.Scale.TextLabels[index];
+
+ Axis yAxis = curve.GetYAxis( pane );
+ if ( yAxis != null && yAxis.Type == AxisType.Text && index >= 0 &&
+ yAxis.Scale.TextLabels != null &&
+ index <= yAxis.Scale.TextLabels.Length )
+ url += "&ytext=" + yAxis.Scale.TextLabels[index];
+
+ return url;
+ }
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ /// <remarks>
+ /// schema started with 10 for ZedGraph version 5
+ /// </remarks>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Link( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _title = info.GetString( "title" );
+ _url = info.GetString( "url" );
+ _target = info.GetString( "target" );
+ _isEnabled = info.GetBoolean( "isEnabled" );
+ Tag = info.GetValue( "Tag", typeof(object) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "title", _title );
+ info.AddValue( "url", _url );
+ info.AddValue( "target", _target );
+ info.AddValue( "isEnabled", _isEnabled );
+ info.AddValue( "Tag", Tag );
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/Location.cs b/ZedGraph/Location.cs
new file mode 100644
index 0000000..5fd2606
--- /dev/null
+++ b/ZedGraph/Location.cs
@@ -0,0 +1,565 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class than contains information about the position of an object on the graph.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.14 $ $Date: 2006-06-24 20:26:43 $ </version>
+ [Serializable]
+ public class Location : ICloneable, ISerializable
+ {
+ #region Private Fields
+ /// <summary> Private field to store the vertical alignment property for
+ /// this object. Use the public property <see cref="Location.AlignV"/>
+ /// to access this value. The value of this field is a <see cref="AlignV"/> enum.
+ /// </summary>
+ private AlignV _alignV;
+ /// <summary> Private field to store the horizontal alignment property for
+ /// this object. Use the public property <see cref="Location.AlignH"/>
+ /// to access this value. The value of this field is a <see cref="AlignH"/> enum.
+ /// </summary>
+ private AlignH _alignH;
+
+ /// <summary> Private fields to store the X and Y coordinate positions for
+ /// this object. Use the public properties <see cref="X"/> and
+ /// <see cref="Y"/> to access these values. The coordinate type stored here is
+ /// dependent upon the setting of <see cref="CoordinateFrame"/>.
+ /// </summary>
+ private double _x,
+ _y,
+ _width,
+ _height;
+
+ /// <summary>
+ /// Private field to store the coordinate system to be used for defining the
+ /// object position. Use the public property
+ /// <see cref="CoordinateFrame"/> to access this value. The coordinate system
+ /// is defined with the <see cref="CoordType"/> enum.
+ /// </summary>
+ private CoordType _coordinateFrame;
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// A horizontal alignment parameter for this object specified
+ /// using the <see cref="AlignH"/> enum type.
+ /// </summary>
+ public AlignH AlignH
+ {
+ get { return _alignH; }
+ set { _alignH = value; }
+ }
+ /// <summary>
+ /// A vertical alignment parameter for this object specified
+ /// using the <see cref="AlignV"/> enum type.
+ /// </summary>
+ public AlignV AlignV
+ {
+ get { return _alignV; }
+ set { _alignV = value; }
+ }
+ /// <summary>
+ /// The coordinate system to be used for defining the object position
+ /// </summary>
+ /// <value> The coordinate system is defined with the <see cref="CoordType"/>
+ /// enum</value>
+ public CoordType CoordinateFrame
+ {
+ get { return _coordinateFrame; }
+ set { _coordinateFrame = value; }
+ }
+ /// <summary>
+ /// The x position of the object.
+ /// </summary>
+ /// <remarks>
+ /// The units of this position
+ /// are specified by the <see cref="CoordinateFrame"/> property.
+ /// The object will be aligned to this position based on the
+ /// <see cref="AlignH"/> property.
+ /// </remarks>
+ public double X
+ {
+ get { return _x; }
+ set { _x = value; }
+ }
+ /// <summary>
+ /// The y position of the object.
+ /// </summary>
+ /// <remarks>
+ /// The units of this position
+ /// are specified by the <see cref="CoordinateFrame"/> property.
+ /// The object will be aligned to this position based on the
+ /// <see cref="AlignV"/> property.
+ /// </remarks>
+ public double Y
+ {
+ get { return _y; }
+ set { _y = value; }
+ }
+ /// <summary>
+ /// The x1 position of the object (an alias for the x position).
+ /// </summary>
+ /// <remarks>
+ /// The units of this position
+ /// are specified by the <see cref="CoordinateFrame"/> property.
+ /// The object will be aligned to this position based on the
+ /// <see cref="AlignH"/> property.
+ /// </remarks>
+ public double X1
+ {
+ get { return _x; }
+ set { _x = value; }
+ }
+ /// <summary>
+ /// The y1 position of the object (an alias for the y position).
+ /// </summary>
+ /// <remarks>
+ /// The units of this position
+ /// are specified by the <see cref="CoordinateFrame"/> property.
+ /// The object will be aligned to this position based on the
+ /// <see cref="AlignV"/> property.
+ /// </remarks>
+ public double Y1
+ {
+ get { return _y; }
+ set { _y = value; }
+ }
+ /// <summary>
+ /// The width of the object.
+ /// </summary>
+ /// <remarks>
+ /// The units of this position are specified by the
+ /// <see cref="CoordinateFrame"/> property.
+ /// </remarks>
+ public double Width
+ {
+ get { return _width; }
+ set { _width = value; }
+ }
+ /// <summary>
+ /// The height of the object.
+ /// </summary>
+ /// <remarks>
+ /// The units of this position are specified by the
+ /// <see cref="CoordinateFrame"/> property.
+ /// </remarks>
+ public double Height
+ {
+ get { return _height; }
+ set { _height = value; }
+ }
+ /// <summary>
+ /// The x2 position of the object.
+ /// </summary>
+ /// <remarks>
+ /// The units of this position are specified by the
+ /// <see cref="CoordinateFrame"/> property.
+ /// The object will be aligned to this position based on the
+ /// <see cref="AlignH"/> property. This position is only used for
+ /// objects such as <see cref="ArrowObj"/>, where it makes sense
+ /// to have a second coordinate. Note that the X2 position is stored
+ /// internally as a <see cref="Width"/> offset from <see cref="X"/>.
+ /// </remarks>
+ public double X2
+ {
+ get { return _x+_width; }
+ //set { width = value-x; }
+ }
+ /// <summary>
+ /// The y2 position of the object.
+ /// </summary>
+ /// <remarks>
+ /// The units of this position
+ /// are specified by the <see cref="CoordinateFrame"/> property.
+ /// The object will be aligned to this position based on the
+ /// <see cref="AlignV"/> property. This position is only used for
+ /// objects such as <see cref="ArrowObj"/>, where it makes sense
+ /// to have a second coordinate. Note that the Y2 position is stored
+ /// internally as a <see cref="Height"/> offset from <see cref="Y"/>.
+ /// </remarks>
+ public double Y2
+ {
+ get { return _y+_height; }
+ //set { height = value-y; }
+ }
+
+ /// <summary>
+ /// The <see cref="RectangleF"/> for this object as defined by the
+ /// <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and
+ /// <see cref="Height"/> properties.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method reduces the precision of the location coordinates from double
+ /// precision to single precision. In some cases, such as <see cref="AxisType.Date" />, it
+ /// may affect the resolution of the point location.
+ /// </remarks>
+ /// <value>A <see cref="RectangleF"/> in <see cref="CoordinateFrame"/>
+ /// units.</value>
+ public RectangleF Rect
+ {
+ get { return new RectangleF( (float)_x, (float)_y, (float)_width, (float)_height ); }
+ set
+ {
+ _x = value.X;
+ _y = value.Y;
+ _width = value.Width;
+ _height = value.Height;
+ }
+ }
+
+ /// <summary>
+ /// The top-left <see cref="PointF"/> for this <see cref="Location"/>.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method reduces the precision of the location coordinates from double
+ /// precision to single precision. In some cases, such as <see cref="AxisType.Date" />, it
+ /// may affect the resolution of the point location.
+ /// </remarks>
+ /// <value>A <see cref="PointF"/> in <see cref="CoordinateFrame"/> units.</value>
+ public PointF TopLeft
+ {
+ get { return new PointF( (float)_x, (float)_y ); }
+ set { _x = value.X; _y = value.Y; }
+ }
+
+ /// <summary>
+ /// The bottom-right <see cref="PointF"/> for this <see cref="Location"/>.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method reduces the precision of the location coordinates from double
+ /// precision to single precision. In some cases, such as <see cref="AxisType.Date" />, it
+ /// may affect the resolution of the point location.
+ /// </remarks>
+ /// <value>A <see cref="PointF"/> in <see cref="CoordinateFrame"/> units.</value>
+ public PointF BottomRight
+ {
+ get { return new PointF( (float)this.X2, (float)this.Y2 ); }
+ //set { this.X2 = value.X; this.Y2 = value.Y; }
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the <see cref="Location"/> class.
+ /// </summary>
+ public Location() : this( 0, 0, CoordType.ChartFraction )
+ {
+ }
+
+ /// <summary>
+ /// Constructor for the <see cref="Location"/> class that specifies the
+ /// x, y position and the <see cref="CoordType"/>.
+ /// </summary>
+ /// <remarks>
+ /// The (x,y) position corresponds to the top-left corner;
+ /// </remarks>
+ /// <param name="x">The x position, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="y">The y position, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum that specifies the
+ /// units for <see paramref="x"/> and <see paramref="y"/></param>
+ public Location( double x, double y, CoordType coordType ) :
+ this( x, y, coordType, AlignH.Left, AlignV.Top )
+ {
+ }
+
+ /// <summary>
+ /// Constructor for the <see cref="Location"/> class that specifies the
+ /// x, y position and the <see cref="CoordType"/>.
+ /// </summary>
+ /// <remarks>
+ /// The (x,y) position corresponds to the top-left corner;
+ /// </remarks>
+ /// <param name="x">The x position, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="y">The y position, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum that specifies the
+ /// units for <see paramref="x"/> and <see paramref="y"/></param>
+ /// <param name="alignH">The <see cref="ZedGraph.AlignH"/> enum that specifies
+ /// the horizontal alignment of the object with respect to the (x,y) location</param>
+ /// <param name="alignV">The <see cref="ZedGraph.AlignV"/> enum that specifies
+ /// the vertical alignment of the object with respect to the (x,y) location</param>
+ public Location( double x, double y, CoordType coordType, AlignH alignH, AlignV alignV )
+ {
+ _x = x;
+ _y = y;
+ _width = 0;
+ _height = 0;
+ _coordinateFrame = coordType;
+ _alignH = alignH;
+ _alignV = alignV;
+ }
+
+ /// <summary>
+ /// Constructor for the <see cref="Location"/> class that specifies the
+ /// (x, y), (width, height), and the <see cref="CoordType"/>.
+ /// </summary>
+ /// <remarks>
+ /// The (x,y) position
+ /// corresponds to the starting position, the (x2, y2) coorresponds to the ending position
+ /// (typically used for <see cref="ArrowObj"/>'s).
+ /// </remarks>
+ /// <param name="x">The x position, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="y">The y position, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="width">The width, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="height">The height, specified in units of <see paramref="coordType"/>.
+ /// </param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum that specifies the
+ /// units for <see paramref="x"/> and <see paramref="y"/></param>
+ /// <param name="alignH">The <see cref="ZedGraph.AlignH"/> enum that specifies
+ /// the horizontal alignment of the object with respect to the (x,y) location</param>
+ /// <param name="alignV">The <see cref="ZedGraph.AlignV"/> enum that specifies
+ /// the vertical alignment of the object with respect to the (x,y) location</param>
+ public Location( double x, double y, double width, double height,
+ CoordType coordType, AlignH alignH, AlignV alignV ) :
+ this( x, y, coordType, alignH, alignV )
+ {
+ _width = width;
+ _height = height;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="Location"/> object from which to copy</param>
+ public Location( Location rhs )
+ {
+ _x = rhs._x;
+ _y = rhs._y;
+ _width = rhs._width;
+ _height = rhs._height;
+ _coordinateFrame = rhs.CoordinateFrame;
+ _alignH = rhs.AlignH;
+ _alignV = rhs.AlignV;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Location Clone()
+ {
+ return new Location( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Location( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _alignV = (AlignV) info.GetValue( "alignV", typeof(AlignV) );
+ _alignH = (AlignH) info.GetValue( "alignH", typeof(AlignH) );
+ _x = info.GetDouble( "x" );
+ _y = info.GetDouble( "y" );
+ _width = info.GetDouble( "width" );
+ _height = info.GetDouble( "height" );
+ _coordinateFrame = (CoordType) info.GetValue( "coordinateFrame", typeof(CoordType) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "alignV", _alignV );
+ info.AddValue( "alignH", _alignH );
+ info.AddValue( "x", _x );
+ info.AddValue( "y", _y );
+ info.AddValue( "width", _width );
+ info.AddValue( "height", _height );
+ info.AddValue( "coordinateFrame", _coordinateFrame );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Transform this <see cref="Location"/> object to display device
+ /// coordinates using the properties of the specified <see cref="GraphPane"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that contains
+ /// the <see cref="Axis"/> classes which will be used for the transform.
+ /// </param>
+ /// <returns>A point in display device coordinates that corresponds to the
+ /// specified user point.</returns>
+ public PointF Transform( PaneBase pane )
+ {
+ return Transform( pane, _x, _y,
+ _coordinateFrame );
+ }
+
+ /// <summary>
+ /// Transform a data point from the specified coordinate type
+ /// (<see cref="CoordType"/>) to display device coordinates (pixels).
+ /// </summary>
+ /// <remarks>
+ /// If <see paramref="pane"/> is not of type <see cref="GraphPane"/>, then
+ /// only the <see cref="CoordType.PaneFraction"/> transformation is available.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that contains
+ /// the <see cref="Axis"/> classes which will be used for the transform.
+ /// </param>
+ /// <param name="x">The x coordinate that defines the point in user
+ /// space.</param>
+ /// <param name="y">The y coordinate that defines the point in user
+ /// space.</param>
+ /// <param name="coord">A <see cref="CoordType"/> type that defines the
+ /// coordinate system in which the X,Y pair is defined.</param>
+ /// <returns>A point in display device coordinates that corresponds to the
+ /// specified user point.</returns>
+ public static PointF Transform( PaneBase pane, double x, double y, CoordType coord )
+ {
+ return pane.TransformCoord( x, y, coord );
+ }
+
+ /// <summary>
+ /// Transform this <see cref="Location"/> from the coordinate system
+ /// as specified by <see cref="CoordinateFrame"/> to the device coordinates
+ /// of the specified <see cref="PaneBase"/> object.
+ /// </summary>
+ /// <remarks>
+ /// The returned
+ /// <see cref="PointF"/> struct represents the top-left corner of the
+ /// object that honors the <see cref="Location"/> properties.
+ /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are honored in
+ /// this transformation.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that contains
+ /// the <see cref="Axis"/> classes which will be used for the transform.
+ /// </param>
+ /// <param name="width">The width of the object in device pixels</param>
+ /// <param name="height">The height of the object in device pixels</param>
+ /// <returns>The top-left corner of the object</returns>
+ public PointF TransformTopLeft( PaneBase pane, float width, float height )
+ {
+ PointF pt = Transform( pane );
+
+ if ( _alignH == AlignH.Right )
+ pt.X -= width;
+ else if ( _alignH == AlignH.Center )
+ pt.X -= width / 2.0F;
+
+ if ( _alignV == AlignV.Bottom )
+ pt.Y -= height;
+ else if ( _alignV == AlignV.Center )
+ pt.Y -= height / 2.0F;
+
+ return pt;
+ }
+
+ /// <summary>
+ /// The <see cref="PointF"/> for this object as defined by the
+ /// <see cref="X"/> and <see cref="Y"/>
+ /// properties.
+ /// </summary>
+ /// <remarks>
+ /// This method transforms the location to output device pixel units.
+ /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are ignored for
+ /// this transformation (see <see cref="TransformTopLeft(PaneBase,float,float)"/>).
+ /// </remarks>
+ /// <value>A <see cref="PointF"/> in pixel units.</value>
+ public PointF TransformTopLeft( PaneBase pane )
+ {
+ return Transform( pane );
+ }
+
+ /// <summary>
+ /// The <see cref="PointF"/> for this object as defined by the
+ /// <see cref="X2"/> and <see cref="Y2"/> properties.
+ /// </summary>
+ /// <remarks>
+ /// This method transforms the location to output device pixel units.
+ /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are ignored for
+ /// this transformation (see <see cref="TransformTopLeft(PaneBase,float,float)"/>).
+ /// </remarks>
+ /// <value>A <see cref="PointF"/> in pixel units.</value>
+ public PointF TransformBottomRight( PaneBase pane )
+ {
+ return Transform( pane, this.X2, this.Y2, _coordinateFrame );
+ }
+
+ /// <summary>
+ /// Transform the <see cref="RectangleF"/> for this object as defined by the
+ /// <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and
+ /// <see cref="Height"/> properties.
+ /// </summary>
+ /// <remarks>
+ /// This method transforms the location to output device pixel units.
+ /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are honored in
+ /// this transformation.
+ /// </remarks>
+ /// <value>A <see cref="RectangleF"/> in pixel units.</value>
+ public RectangleF TransformRect( PaneBase pane )
+ {
+ PointF pix1 = TransformTopLeft( pane );
+ PointF pix2 = TransformBottomRight( pane );
+ //PointF pix3 = TransformTopLeft( pane, pix2.X - pix1.X, pix2.Y - pix1.Y );
+
+ return new RectangleF( pix1.X, pix1.Y, Math.Abs(pix2.X - pix1.X), Math.Abs(pix2.Y - pix1.Y) );
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/LogScale.cs b/ZedGraph/LogScale.cs
new file mode 100644
index 0000000..6596aa1
--- /dev/null
+++ b/ZedGraph/LogScale.cs
@@ -0,0 +1,442 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The LogScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.Log" />.
+ /// </summary>
+ /// <remarks>
+ /// LogScale is a non-linear axis in which the values are scaled using the base 10
+ /// <see cref="Math.Log(double)" />
+ /// function.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.12 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ class LogScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public LogScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="LogScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="LogScale" /></param>
+ public LogScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new LogScale( this, owner );
+ }
+
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Return the <see cref="AxisType" /> for this <see cref="Scale" />, which is
+ /// <see cref="AxisType.Log" />.
+ /// </summary>
+ public override AxisType Type
+ {
+ get { return AxisType.Log; }
+ }
+
+ /// <summary>
+ /// Gets or sets the minimum value for this scale.
+ /// </summary>
+ /// <remarks>
+ /// The set property is specifically adapted for <see cref="AxisType.Log" /> scales,
+ /// in that it automatically limits the setting to values greater than zero.
+ /// </remarks>
+ public override double Min
+ {
+ get { return _min; }
+ set { if ( value > 0 ) _min = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum value for this scale.
+ /// </summary>
+ /// <remarks>
+ /// The set property is specifically adapted for <see cref="AxisType.Log" /> scales,
+ /// in that it automatically limits the setting to values greater than zero.
+ /// <see cref="XDate" /> struct.
+ /// </remarks>
+ public override double Max
+ {
+ get { return _max; }
+ set { if ( value > 0 ) _max = value; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Setup some temporary transform values in preparation for rendering the <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>
+ /// This method is typically called by the parent <see cref="GraphPane"/>
+ /// object as part of the <see cref="GraphPane.Draw"/> method. It is also
+ /// called by <see cref="GraphPane.GeneralTransform(double,double,CoordType)"/> and
+ /// <see cref="GraphPane.ReverseTransform( PointF, out double, out double )"/>
+ /// methods to setup for coordinate transformations.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="axis">
+ /// The parent <see cref="Axis" /> for this <see cref="Scale" />
+ /// </param>
+ override public void SetupScaleData( GraphPane pane, Axis axis )
+ {
+ base.SetupScaleData( pane, axis );
+
+ _minLinTemp = Linearize( _min );
+ _maxLinTemp = Linearize( _max );
+ }
+
+ /// <summary>
+ /// Convert a value to its linear equivalent for this type of scale.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to just return the value unchanged. However,
+ /// for <see cref="AxisType.Log" /> and <see cref="AxisType.Exponent" />,
+ /// it returns the log or power equivalent.
+ /// </remarks>
+ /// <param name="val">The value to be converted</param>
+ override public double Linearize( double val )
+ {
+ return SafeLog( val );
+ }
+
+ /// <summary>
+ /// Convert a value from its linear equivalent to its actual scale value
+ /// for this type of scale.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to just return the value unchanged. However,
+ /// for <see cref="AxisType.Log" /> and <see cref="AxisType.Exponent" />,
+ /// it returns the anti-log or inverse-power equivalent.
+ /// </remarks>
+ /// <param name="val">The value to be converted</param>
+ override public double DeLinearize( double val )
+ {
+ return Math.Pow( 10.0, val );
+ }
+
+ /// <summary>
+ /// Determine the value for any major tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double)
+ /// </param>
+ /// <param name="tic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified major tic value (floating point double).
+ /// </returns>
+ override internal double CalcMajorTicValue( double baseVal, double tic )
+ {
+ return baseVal + (double)tic * CyclesPerStep;
+
+ // double val = baseVal + (double)tic * CyclesPerStep;
+ // double frac = val - Math.Floor( val );
+ }
+
+ /// <summary>
+ /// Determine the value for any minor tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double). This tic value is the base
+ /// reference for all tics (including minor ones).
+ /// </param>
+ /// <param name="iTic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified minor tic value (floating point double).
+ /// </returns>
+ override internal double CalcMinorTicValue( double baseVal, int iTic )
+ {
+ double[] dLogVal = { 0, 0.301029995663981, 0.477121254719662, 0.602059991327962,
+ 0.698970004336019, 0.778151250383644, 0.845098040014257,
+ 0.903089986991944, 0.954242509439325, 1 };
+
+ return baseVal + Math.Floor( (double) iTic / 9.0 ) + dLogVal[( iTic + 9 ) % 9];
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first minor tic mark
+ /// </summary>
+ /// <param name="baseVal">
+ /// The value of the first major tic for the axis.
+ /// </param>
+ /// <returns>
+ /// The ordinal position of the first minor tic, relative to the first major tic.
+ /// This value can be negative (e.g., -3 means the first minor tic is 3 minor step
+ /// increments before the first major tic.
+ /// </returns>
+ override internal int CalcMinorStart( double baseVal )
+ {
+ return -9;
+ }
+
+ /// <summary>
+ /// Determine the value for the first major tic.
+ /// </summary>
+ /// <remarks>
+ /// This is done by finding the first possible value that is an integral multiple of
+ /// the step size, taking into account the date/time units if appropriate.
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <returns>
+ /// First major tic value (floating point double).
+ /// </returns>
+ override internal double CalcBaseTic()
+ {
+ if ( _baseTic != PointPair.Missing )
+ return _baseTic;
+ else
+ {
+ // go to the nearest even multiple of the step size
+ return Math.Ceiling( Scale.SafeLog( _min ) - 0.00000001 );
+ }
+
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first and last major axis label.
+ /// </summary>
+ /// <returns>
+ /// This is the total number of major tics for this axis.
+ /// </returns>
+ override internal int CalcNumTics()
+ {
+ int nTics = 1;
+
+ //iStart = (int) ( Math.Ceiling( SafeLog( this.min ) - 1.0e-12 ) );
+ //iEnd = (int) ( Math.Floor( SafeLog( this.max ) + 1.0e-12 ) );
+
+ //nTics = (int)( ( Math.Floor( Scale.SafeLog( _max ) + 1.0e-12 ) ) -
+ // ( Math.Ceiling( Scale.SafeLog( _min ) - 1.0e-12 ) ) + 1 ) / CyclesPerStep;
+ nTics = (int)( ( Scale.SafeLog( _max ) - Scale.SafeLog( _min ) ) / CyclesPerStep ) + 1;
+
+ if ( nTics < 1 )
+ nTics = 1;
+ else if ( nTics > 1000 )
+ nTics = 1000;
+
+ return nTics;
+ }
+
+ private double CyclesPerStep
+ {
+ //get { return (int)Math.Max( Math.Floor( Scale.SafeLog( _majorStep ) ), 1 ); }
+ get { return _majorStep; }
+ }
+
+ /// <summary>
+ /// Select a reasonable base 10 logarithmic axis scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.Log"/> type axes, and it
+ /// is called by the general <see cref="PickScale"/> method. The scale range is chosen
+ /// based always on powers of 10 (full log cycles). This
+ /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/> autorange settings.
+ /// In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/>
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values. For log axes, the MinorStep
+ /// value is not used.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="PickScale"/>
+ /// <seealso cref="AxisType.Log"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ // Majorstep is always 1 for log scales
+ if ( _majorStepAuto )
+ _majorStep = 1.0;
+
+ _mag = 0; // Never use a magnitude shift for log scales
+ //this.numDec = 0; // The number of decimal places to display is not used
+
+ // Check for bad data range
+ if ( _min <= 0.0 && _max <= 0.0 )
+ {
+ _min = 1.0;
+ _max = 10.0;
+ }
+ else if ( _min <= 0.0 )
+ {
+ _min = _max / 10.0;
+ }
+ else if ( _max <= 0.0 )
+ {
+ _max = _min * 10.0;
+ }
+
+ // Test for trivial condition of range = 0 and pick a suitable default
+ if ( _max - _min < 1.0e-20 )
+ {
+ if ( _maxAuto )
+ _max = _max * 2.0;
+ if ( _minAuto )
+ _min = _min / 2.0;
+ }
+
+ // Get the nearest power of 10 (no partial log cycles allowed)
+ if ( _minAuto )
+ _min = Math.Pow( (double) 10.0,
+ Math.Floor( Math.Log10( _min ) ) );
+ if ( _maxAuto )
+ _max = Math.Pow( (double) 10.0,
+ Math.Ceiling( Math.Log10( _max ) ) );
+
+ }
+
+ /// <summary>
+ /// Make a value label for an <see cref="AxisType.Log" /> <see cref="Axis" />.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="Scale.IsLog"/>)
+ /// and text (<see cref="Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ override internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ if ( _isUseTenPower )
+ return string.Format( "{0:F0}", dVal );
+ else
+ return Math.Pow( 10.0, dVal ).ToString( _format );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected LogScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/MajorGrid.cs b/ZedGraph/MajorGrid.cs
new file mode 100644
index 0000000..119f8ea
--- /dev/null
+++ b/ZedGraph/MajorGrid.cs
@@ -0,0 +1,199 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles the data associated with the major grid lines on the chart.
+ /// Inherits from <see cref="MinorGrid" />.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class MajorGrid : MinorGrid, ICloneable, ISerializable
+ {
+ internal bool _isZeroLine;
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ public MajorGrid()
+ {
+ _dashOn = Default.DashOn;
+ _dashOff = Default.DashOff;
+ _penWidth = Default.PenWidth;
+ _isVisible = Default.IsVisible;
+ _color = Default.Color;
+ _isZeroLine = Default.IsZeroLine;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">The source <see cref="MajorGrid" /> to be copied.</param>
+ public MajorGrid( MajorGrid rhs ) : base( rhs )
+ {
+ _isZeroLine = rhs._isZeroLine;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new MajorGrid Clone()
+ {
+ return new MajorGrid( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a boolean value that determines if a line will be drawn at the
+ /// zero value for the axis.
+ /// </summary>
+ /// <remarks>
+ /// The zero line is a line that divides the negative values from the positive values.
+ /// The default is set according to
+ /// <see cref="XAxis.Default.IsZeroLine"/>, <see cref="YAxis.Default.IsZeroLine"/>,
+ /// <see cref="Y2Axis.Default.IsZeroLine"/>,
+ /// </remarks>
+ /// <value>true to show the zero line, false otherwise</value>
+ public bool IsZeroLine
+ {
+ get { return _isZeroLine; }
+ set { _isZeroLine = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected MajorGrid( SerializationInfo info, StreamingContext context ) :
+ base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _isZeroLine = info.GetBoolean( "isZeroLine" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+
+ info.AddValue( "isZeroLine", _isZeroLine );
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="MajorGrid"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ /// <summary>
+ /// The default "dash on" size for drawing the <see cref="Axis"/> grid
+ /// (<see cref="MinorGrid.DashOn"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float DashOn = 1.0F;
+ /// <summary>
+ /// The default "dash off" size for drawing the <see cref="Axis"/> grid
+ /// (<see cref="MinorGrid.DashOff"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float DashOff = 5.0F;
+ /// <summary>
+ /// The default pen width for drawing the <see cref="Axis"/> grid
+ /// (<see cref="MinorGrid.PenWidth"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The default color for the <see cref="Axis"/> grid lines
+ /// (<see cref="MinorGrid.Color"/> property). This color only affects the
+ /// grid lines.
+ /// </summary>
+ public static Color Color = Color.Black;
+
+ /// <summary>
+ /// The default display mode for the <see cref="Axis"/> grid lines
+ /// (<see cref="MinorGrid.IsVisible"/> property). true
+ /// to show the grid lines, false to hide them.
+ /// </summary>
+ public static bool IsVisible = false;
+
+ /// <summary>
+ /// The default boolean value that determines if a line will be drawn at the
+ /// zero value for the axis.
+ /// </summary>
+ /// <remarks>
+ /// The zero line is a line that divides the negative values from the positive values.
+ /// The default is set according to
+ /// <see cref="XAxis.Default.IsZeroLine"/>, <see cref="YAxis.Default.IsZeroLine"/>,
+ /// <see cref="Y2Axis.Default.IsZeroLine"/>,
+ /// </remarks>
+ /// <value>true to show the zero line, false otherwise</value>
+ public static bool IsZeroLine = false;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/MajorTic.cs b/ZedGraph/MajorTic.cs
new file mode 100644
index 0000000..a2dfc36
--- /dev/null
+++ b/ZedGraph/MajorTic.cs
@@ -0,0 +1,243 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that holds the specific properties for the major tics. Inherits from
+ /// <see cref="MinorTic" />.
+ /// </summary>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class MajorTic : MinorTic, ICloneable, ISerializable
+ {
+ internal bool _isBetweenLabels;
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for <see cref="MajorTic" />.
+ /// </summary>
+ public MajorTic()
+ {
+ _size = Default.Size;
+ _color = Default.Color;
+ _penWidth = Default.PenWidth;
+
+ this.IsOutside = Default.IsOutside;
+ this.IsInside = Default.IsInside;
+ this.IsOpposite = Default.IsOpposite;
+ _isCrossOutside = Default.IsCrossOutside;
+ _isCrossInside = Default.IsCrossInside;
+
+ _isBetweenLabels = false;
+ }
+
+ /// <summary>
+ /// Copy constructor.
+ /// </summary>
+ /// <param name="rhs">The <see cref="MajorTic" /> that is to be copied.</param>
+ public MajorTic( MajorTic rhs )
+ : base( rhs )
+ {
+ _isBetweenLabels = rhs._isBetweenLabels;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new MajorTic Clone()
+ {
+ return new MajorTic( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a property that determines whether or not the major tics will be drawn
+ /// inbetween the labels, rather than right at the labels.
+ /// </summary>
+ /// <remarks>
+ /// Note that this setting is only
+ /// applicable if <see cref="Axis.Type"/> = <see cref="AxisType.Text"/>.
+ /// </remarks>
+ /// <value>true to place the text between the labels for text axes, false otherwise</value>
+ /// <seealso cref="MinorTic.IsOutside"/>
+ /// <seealso cref="MinorTic.IsInside"/>
+ /// <seealso cref="MinorTic.IsOpposite"/>
+ /// <seealso cref="MinorTic.IsCrossOutside"/>
+ /// <seealso cref="MinorTic.IsCrossInside"/>
+ public bool IsBetweenLabels
+ {
+ get { return _isBetweenLabels; }
+ set { _isBetweenLabels = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected MajorTic( SerializationInfo info, StreamingContext context ) :
+ base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch2 = info.GetInt32( "schema2" );
+
+ _isBetweenLabels = info.GetBoolean( "isBetweenLabels" );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+
+ info.AddValue( "isBetweenLabels", _isBetweenLabels );
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="MinorTic"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ // Default Axis Properties
+ /// <summary>
+ /// The default size for the <see cref="Axis"/> tic marks.
+ /// (<see cref="MinorTic.Size"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float Size = 5;
+ /// <summary>
+ /// The default pen width for drawing the <see cref="Axis"/> tic marks.
+ /// (<see cref="MinorTic.PenWidth"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The display mode for the <see cref="Axis"/> major outside tic marks
+ /// (<see cref="MinorTic.IsOutside"/> property).
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </summary>
+ /// <value>true to show the major tic marks (outside the axis),
+ /// false otherwise</value>
+ public static bool IsOutside = true;
+ /// <summary>
+ /// The display mode for the <see cref="Axis"/> major inside tic marks
+ /// (<see cref="MinorTic.IsInside"/> property).
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </summary>
+ /// <value>true to show the major tic marks (inside the axis),
+ /// false otherwise</value>
+ public static bool IsInside = true;
+ /// <summary>
+ /// The display mode for the <see cref="Axis"/> major opposite tic marks
+ /// (<see cref="MinorTic.IsOpposite"/> property).
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </summary>
+ /// <value>true to show the major tic marks
+ /// (inside the axis on the opposite side),
+ /// false otherwise</value>
+ public static bool IsOpposite = true;
+
+ /// <summary>
+ /// The default display mode for the <see cref="Axis"/> major outside
+ /// "cross" tic marks (<see cref="MinorTic.IsCrossOutside"/> property).
+ /// </summary>
+ /// <remarks>
+ /// The "cross" tics are a special, additional set of tic marks that
+ /// always appear on the actual axis, even if it has been shifted due
+ /// to the <see cref="Axis.Cross" /> setting. The other tic marks are always
+ /// fixed to the edges of the <see cref="Chart.Rect"/>. The cross tics
+ /// are normally not displayed, since, if <see cref="Axis.CrossAuto" /> is true,
+ /// they will exactly overlay the "normal" and "inside" tics. If
+ /// <see cref="Axis.CrossAuto"/> is false, then you will most likely want to
+ /// enable the cross tics.
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major cross tic marks, false otherwise</value>
+ public static bool IsCrossOutside = false;
+ /// <summary>
+ /// The default display mode for the <see cref="Axis"/> major inside
+ /// "cross" tic marks (<see cref="MinorTic.IsCrossInside"/> property).
+ /// </summary>
+ /// <remarks>
+ /// The "cross" tics are a special, additional set of tic marks that
+ /// always appear on the actual axis, even if it has been shifted due
+ /// to the <see cref="Axis.Cross" /> setting. The other tic marks are always
+ /// fixed to the edges of the <see cref="Chart.Rect"/>. The cross tics
+ /// are normally not displayed, since, if <see cref="Axis.CrossAuto" /> is true,
+ /// they will exactly overlay the "normal" and "inside" tics. If
+ /// <see cref="Axis.CrossAuto"/> is false, then you will most likely want to
+ /// enable the cross tics.
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major cross tic marks, false otherwise</value>
+ public static bool IsCrossInside = false;
+
+ /// <summary>
+ /// The default color for major tics (<see cref="MinorTic.Color"/> property).
+ /// </summary>
+ public static Color Color = Color.Black;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Margin.cs b/ZedGraph/Margin.cs
new file mode 100644
index 0000000..f2c8ae2
--- /dev/null
+++ b/ZedGraph/Margin.cs
@@ -0,0 +1,263 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that handles that stores the margin properties for the GraphPane
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class Margin : ICloneable, ISerializable
+ {
+ /// <summary>
+ /// Private fields that store the size of the margin around the edge of the pane which will be
+ /// kept blank. Use the public properties <see cref="Margin.Left"/>, <see cref="Margin.Right"/>,
+ /// <see cref="Margin.Top"/>, <see cref="Margin.Bottom"/> to access these values.
+ /// </summary>
+ /// <value>Units are points (1/72 inch)</value>
+ protected float _left,
+ _right,
+ _top,
+ _bottom;
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructor to build a <see cref="Margin" /> from the default values.
+ /// </summary>
+ public Margin()
+ {
+ _left = Default.Left;
+ _right = Default.Right;
+ _top = Default.Top;
+ _bottom = Default.Bottom;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">the <see cref="Margin" /> instance to be copied.</param>
+ public Margin( Margin rhs )
+ {
+ _left = rhs._left;
+ _right = rhs._right;
+ _top = rhs._top;
+ _bottom = rhs._bottom;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Margin Clone()
+ {
+ return new Margin( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a float value that determines the margin area between the left edge of the
+ /// <see cref="PaneBase.Rect"/> rectangle and the features of the graph.
+ /// </summary>
+ /// <value>This value is in units of points (1/72 inch), and is scaled
+ /// linearly with the graph size.</value>
+ /// <seealso cref="Default.Left"/>
+ /// <seealso cref="PaneBase.IsFontsScaled"/>
+ /// <seealso cref="Right"/>
+ /// <seealso cref="Top"/>
+ /// <seealso cref="Bottom"/>
+ public float Left
+ {
+ get { return _left; }
+ set { _left = value; }
+ }
+ /// <summary>
+ /// Gets or sets a float value that determines the margin area between the right edge of the
+ /// <see cref="PaneBase.Rect"/> rectangle and the features of the graph.
+ /// </summary>
+ /// <value>This value is in units of points (1/72 inch), and is scaled
+ /// linearly with the graph size.</value>
+ /// <seealso cref="Default.Right"/>
+ /// <seealso cref="PaneBase.IsFontsScaled"/>
+ /// <seealso cref="Left"/>
+ /// <seealso cref="Top"/>
+ /// <seealso cref="Bottom"/>
+ public float Right
+ {
+ get { return _right; }
+ set { _right = value; }
+ }
+ /// <summary>
+ /// Gets or sets a float value that determines the margin area between the top edge of the
+ /// <see cref="PaneBase.Rect"/> rectangle and the features of the graph.
+ /// </summary>
+ /// <value>This value is in units of points (1/72 inch), and is scaled
+ /// linearly with the graph size.</value>
+ /// <seealso cref="Default.Top"/>
+ /// <seealso cref="PaneBase.IsFontsScaled"/>
+ /// <seealso cref="Left"/>
+ /// <seealso cref="Right"/>
+ /// <seealso cref="Bottom"/>
+ public float Top
+ {
+ get { return _top; }
+ set { _top = value; }
+ }
+ /// <summary>
+ /// Gets or sets a float value that determines the margin area between the bottom edge of the
+ /// <see cref="PaneBase.Rect"/> rectangle and the features of the graph.
+ /// </summary>
+ /// <value>This value is in units of points (1/72 inch), and is scaled
+ /// linearly with the graph size.</value>
+ /// <seealso cref="Default.Bottom"/>
+ /// <seealso cref="PaneBase.IsFontsScaled"/>
+ /// <seealso cref="Left"/>
+ /// <seealso cref="Right"/>
+ /// <seealso cref="Top"/>
+ public float Bottom
+ {
+ get { return _bottom; }
+ set { _bottom = value; }
+ }
+
+ /// <summary>
+ /// Concurrently sets all outer margin values to a single value.
+ /// </summary>
+ /// <value>This value is in units of points (1/72 inch), and is scaled
+ /// linearly with the graph size.</value>
+ /// <seealso cref="PaneBase.IsFontsScaled"/>
+ /// <seealso cref="Bottom"/>
+ /// <seealso cref="Left"/>
+ /// <seealso cref="Right"/>
+ /// <seealso cref="Top"/>
+ public float All
+ {
+ set
+ {
+ _bottom = value;
+ _top = value;
+ _left = value;
+ _right = value;
+ }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Margin( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _left = info.GetSingle( "left" );
+ _right = info.GetSingle( "right" );
+ _top = info.GetSingle( "top" );
+ _bottom = info.GetSingle( "bottom" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "left", _left );
+ info.AddValue( "right", _right );
+ info.AddValue( "top", _top );
+ info.AddValue( "bottom", _bottom );
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the default property values for the <see cref="Margin"/> class.
+ /// </summary>
+ public class Default
+ {
+ /// <summary>
+ /// The default value for the <see cref="Margin.Left"/> property, which is
+ /// the size of the space on the left side of the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <value>Units are points (1/72 inch)</value>
+ public static float Left = 10.0F;
+ /// <summary>
+ /// The default value for the <see cref="Margin.Right"/> property, which is
+ /// the size of the space on the right side of the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <value>Units are points (1/72 inch)</value>
+ public static float Right = 10.0F;
+ /// <summary>
+ /// The default value for the <see cref="Margin.Top"/> property, which is
+ /// the size of the space on the top side of the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <value>Units are points (1/72 inch)</value>
+ public static float Top = 10.0F;
+ /// <summary>
+ /// The default value for the <see cref="Margin.Bottom"/> property, which is
+ /// the size of the space on the bottom side of the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <value>Units are points (1/72 inch)</value>
+ public static float Bottom = 10.0F;
+
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/MasterPane.cs b/ZedGraph/MasterPane.cs
new file mode 100644
index 0000000..6aca1fa
--- /dev/null
+++ b/ZedGraph/MasterPane.cs
@@ -0,0 +1,1178 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Drawing.Text;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="GraphPane"/> objects
+ /// organized together in some form.
+ /// </summary>
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.26 $ $Date: 2007-11-05 18:28:56 $ </version>
+ [Serializable]
+ public class MasterPane : PaneBase, ICloneable, ISerializable, IDeserializationCallback
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// Private field that holds a collection of <see cref="GraphPane"/> objects for inclusion
+ /// in this <see cref="MasterPane"/>. Use the public property <see cref="PaneList"/>
+ /// to access this collection.
+ /// </summary>
+ internal PaneList _paneList;
+ /// <summary>
+ /// Private field that sets the amount of space between the GraphPanes. Use the public property
+ /// <see cref="InnerPaneGap"/> to access this value;
+ /// </summary>
+ internal float _innerPaneGap;
+ /// <summary>
+ ///Private field that stores a boolean value which signifies whether all
+ ///<see cref="ZedGraph.GraphPane"/>s in the chart use the same entries in their
+ ///<see cref="Legend"/> If set to true, only one set of entries will be displayed in
+ ///this <see cref="Legend"/> instance. If set to false, this instance will display all
+ ///entries from all <see cref="ZedGraph.GraphPane"/>s.
+ /// </summary>
+ private bool _isUniformLegendEntries;
+ /// <summary>
+ /// private field that determines if the
+ /// <see cref="DoLayout(Graphics)" />
+ /// function will automatically set
+ /// the <see cref="PaneBase.BaseDimension" /> of each <see cref="GraphPane" /> in the
+ /// <see cref="PaneList" /> such that the scale factors have the same value.
+ /// </summary>
+ private bool _isCommonScaleFactor;
+
+ /// <summary>
+ /// private field that saves the paneLayout format specified when
+ /// <see cref="SetLayout(Graphics,PaneLayout)"/> was called. This value will
+ /// default to <see cref="MasterPane.Default.PaneLayout"/> if
+ /// <see cref="SetLayout(Graphics,PaneLayout)"/> (or an overload) was never called.
+ /// </summary>
+ internal PaneLayout _paneLayout;
+
+ /// <summary>
+ /// Private field that stores the boolean value that determines whether
+ /// <see cref="_countList"/> is specifying rows or columns.
+ /// </summary>
+ internal bool _isColumnSpecified;
+ /// <summary>
+ /// private field that stores the row/column item count that was specified to the
+ /// <see cref="SetLayout(Graphics,bool,int[],float[])"/> method. This values will be
+ /// null if <see cref="SetLayout(Graphics,bool,int[],float[])"/> was never called.
+ /// </summary>
+ internal int[] _countList;
+
+ /// <summary>
+ /// private field that stores the row/column size proportional values as specified
+ /// to the <see cref="SetLayout(Graphics,bool,int[],float[])"/> method. This
+ /// value will be null if <see cref="SetLayout(Graphics,bool,int[],float[])"/>
+ /// was never called.
+ /// </summary>
+ internal float[] _prop;
+
+/* /// <summary>
+ /// private field to store the <see cref="PaneLayoutMgr" /> instance, which
+ /// manages the persistence and handling of pane layout information.
+ /// </summary>
+ private PaneLayoutMgr _paneLayoutMgr;
+*/
+ /// <summary>
+ /// private field that determines if anti-aliased drawing will be forced on. Use the
+ /// public property <see cref="IsAntiAlias"/> to access this value.
+ /// </summary>
+ private bool _isAntiAlias = false;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="MasterPane"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ /// <summary>
+ /// The default pane layout for
+ /// <see cref="DoLayout(Graphics)"/>
+ /// method calls.
+ /// </summary>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ /// <seealso cref="ReSize(Graphics,RectangleF)" />
+ public static PaneLayout PaneLayout = PaneLayout.SquareColPreferred;
+
+ /// <summary>
+ /// The default value for the <see cref="Default.InnerPaneGap"/> property.
+ /// This is the size of the margin between adjacent <see cref="GraphPane"/>
+ /// objects, in units of points (1/72 inch).
+ /// </summary>
+ /// <seealso cref="MasterPane.InnerPaneGap"/>
+ public static float InnerPaneGap = 10;
+
+ /// <summary>
+ /// The default value for the <see cref="Legend.IsVisible"/> property for
+ /// the <see cref="MasterPane"/> class.
+ /// </summary>
+ public static bool IsShowLegend = false;
+ /// <summary>
+ /// The default value for the <see cref="IsUniformLegendEntries"/> property.
+ /// </summary>
+ public static bool IsUniformLegendEntries = false;
+ /// <summary>
+ /// The default value for the <see cref="IsCommonScaleFactor"/> property.
+ /// </summary>
+ public static bool IsCommonScaleFactor = false;
+ }
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="PaneList"/> collection instance that holds the list of
+ /// <see cref="GraphPane"/> objects that are included in this <see cref="MasterPane"/>.
+ /// </summary>
+ /// <seealso cref="Add"/>
+ /// <seealso cref="MasterPane.this[int]"/>
+ public PaneList PaneList
+ {
+ get { return _paneList; }
+ set { _paneList = value; }
+ }
+/*
+ /// <summary>
+ /// Gets the <see cref="PaneLayoutMgr" /> instance, which manages the pane layout
+ /// settings, and handles the layout functions.
+ /// </summary>
+ /// <seealso cref="ZedGraph.PaneLayoutMgr.SetLayout(PaneLayout)" />
+ /// <seealso cref="ZedGraph.PaneLayoutMgr.SetLayout(int,int)" />
+ /// <seealso cref="ZedGraph.PaneLayoutMgr.SetLayout(bool,int[])" />
+ /// <seealso cref="ZedGraph.PaneLayoutMgr.SetLayout(bool,int[],float[])" />
+ /// <seealso cref="ReSize" />
+ public PaneLayoutMgr PaneLayoutMgr
+ {
+ get { return _paneLayoutMgr; }
+ }
+*/
+ /// <summary>
+ /// Gets or sets the size of the margin between adjacent <see cref="GraphPane"/>
+ /// objects.
+ /// </summary>
+ /// <remarks>This property is scaled according to <see cref="PaneBase.CalcScaleFactor"/>,
+ /// based on <see cref="PaneBase.BaseDimension"/>. The default value comes from
+ /// <see cref="Default.InnerPaneGap"/>.
+ /// </remarks>
+ /// <value>The value is in points (1/72nd inch).</value>
+ public float InnerPaneGap
+ {
+ get { return _innerPaneGap; }
+ set { _innerPaneGap = value; }
+ }
+ /// <summary>
+ /// Gets or set the value of the <see cref="IsUniformLegendEntries"/>
+ /// </summary>
+ public bool IsUniformLegendEntries
+ {
+ get { return (_isUniformLegendEntries); }
+ set { _isUniformLegendEntries = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the
+ /// <see cref="DoLayout(Graphics)" /> method will automatically set the
+ /// <see cref="PaneBase.BaseDimension" />
+ /// of each <see cref="GraphPane" /> in the <see cref="PaneList" /> such that the
+ /// scale factors have the same value.
+ /// </summary>
+ /// <remarks>
+ /// The scale factors, calculated by <see cref="PaneBase.CalcScaleFactor" />, determine
+ /// scaled font sizes, tic lengths, etc. This function will insure that for
+ /// multiple graphpanes, a certain specified font size will be the same for
+ /// all the panes.
+ /// </remarks>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ /// <seealso cref="ReSize(Graphics,RectangleF)" />
+ public bool IsCommonScaleFactor
+ {
+ get { return _isCommonScaleFactor; }
+ set { _isCommonScaleFactor = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if all drawing operations for this
+ /// <see cref="MasterPane" /> will be forced to operate in Anti-alias mode.
+ /// Note that if this value is set to "true", it overrides the setting for sub-objects.
+ /// Otherwise, the sub-object settings (such as <see cref="FontSpec.IsAntiAlias"/>)
+ /// will be honored.
+ /// </summary>
+ public bool IsAntiAlias
+ {
+ get { return _isAntiAlias; }
+ set { _isAntiAlias = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the class. Sets the <see cref="PaneBase.Rect"/> to (0, 0, 500, 375).
+ /// </summary>
+ public MasterPane() : this( "", new RectangleF( 0, 0, 500, 375 ) )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor for the class. Specifies the <see cref="PaneBase.Title"/> of
+ /// the <see cref="MasterPane"/>, and the size of the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ public MasterPane( string title, RectangleF paneRect ) : base( title, paneRect )
+ {
+ _innerPaneGap = Default.InnerPaneGap;
+
+ //_paneLayoutMgr = new PaneLayoutMgr();
+
+ _isUniformLegendEntries = Default.IsUniformLegendEntries ;
+ _isCommonScaleFactor = Default.IsCommonScaleFactor;
+
+ _paneList = new PaneList();
+
+ _legend.IsVisible = Default.IsShowLegend;
+
+ _isAntiAlias = false;
+
+ InitLayout();
+ }
+
+ private void InitLayout()
+ {
+ _paneLayout = Default.PaneLayout;
+ _countList = null;
+ _isColumnSpecified = false;
+ _prop = null;
+ }
+
+ /// <summary>
+ /// The Copy Constructor - Make a deep-copy clone of this class instance.
+ /// </summary>
+ /// <param name="rhs">The <see cref="MasterPane"/> object from which to copy</param>
+ public MasterPane( MasterPane rhs ) : base( rhs )
+ {
+ // copy all the value types
+ //_paneLayoutMgr = rhs._paneLayoutMgr.Clone();
+ _innerPaneGap = rhs._innerPaneGap;
+ _isUniformLegendEntries = rhs._isUniformLegendEntries;
+ _isCommonScaleFactor = rhs._isCommonScaleFactor;
+
+ // Then, fill in all the reference types with deep copies
+ _paneList = rhs._paneList.Clone();
+
+ _paneLayout = rhs._paneLayout;
+ _countList = rhs._countList;
+ _isColumnSpecified = rhs._isColumnSpecified;
+ _prop = rhs._prop;
+ _isAntiAlias = rhs._isAntiAlias;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" /> to make a deep copy.
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public MasterPane Clone()
+ {
+ return new MasterPane( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ // schema changed to 2 with addition of 'prop'
+ // schema changed to 11 with addition of 'isAntiAlias'
+ public const int schema2 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected MasterPane( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _paneList = (PaneList) info.GetValue( "paneList", typeof(PaneList) );
+ //_paneLayoutMgr = (PaneLayoutMgr) info.GetValue( "paneLayoutMgr", typeof(PaneLayoutMgr) );
+ _innerPaneGap = info.GetSingle( "innerPaneGap" );
+
+ _isUniformLegendEntries = info.GetBoolean( "isUniformLegendEntries" );
+ _isCommonScaleFactor = info.GetBoolean( "isCommonScaleFactor" );
+
+ _paneLayout = (PaneLayout)info.GetValue( "paneLayout", typeof( PaneLayout ) );
+ _countList = (int[])info.GetValue( "countList", typeof( int[] ) );
+
+ _isColumnSpecified = info.GetBoolean( "isColumnSpecified" );
+ _prop = (float[])info.GetValue( "prop", typeof( float[] ) );
+
+ if ( sch >= 11 )
+ _isAntiAlias = info.GetBoolean( "isAntiAlias" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+
+ info.AddValue( "paneList", _paneList );
+ //info.AddValue( "paneLayoutMgr", _paneLayoutMgr );
+ info.AddValue( "innerPaneGap", _innerPaneGap );
+
+ info.AddValue( "isUniformLegendEntries", _isUniformLegendEntries );
+ info.AddValue( "isCommonScaleFactor", _isCommonScaleFactor );
+
+ info.AddValue( "paneLayout", _paneLayout );
+ info.AddValue( "countList", _countList );
+ info.AddValue( "isColumnSpecified", _isColumnSpecified );
+ info.AddValue( "prop", _prop );
+
+ info.AddValue( "isAntiAlias", _isAntiAlias );
+ }
+
+ /// <summary>
+ /// Respond to the callback when the MasterPane objects are fully initialized.
+ /// </summary>
+ /// <param name="sender"></param>
+ public void OnDeserialization(object? sender)
+ {
+ Bitmap bitmap = new Bitmap( 10, 10 );
+ Graphics g = Graphics.FromImage( bitmap );
+ ReSize( g, _rect );
+ }
+ #endregion
+
+ #region List Methods
+ /// <summary>
+ /// Indexer to access the specified <see cref="GraphPane"/> object from <see cref="PaneList"/>
+ /// by its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="GraphPane"/> object to be accessed.</param>
+ /// <value>A <see cref="GraphPane"/> object reference.</value>
+ public GraphPane this[ int index ]
+ {
+ get { return( (GraphPane) _paneList[index] ); }
+ set { _paneList[index] = value; }
+ }
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="GraphPane"/> object from <see cref="PaneList"/>
+ /// by its <see cref="PaneBase.Title"/> string.
+ /// </summary>
+ /// <param name="title">The string title of the
+ /// <see cref="GraphPane"/> object to be accessed.</param>
+ /// <value>A <see cref="GraphPane"/> object reference.</value>
+ public GraphPane this[ string title ]
+ {
+ get { return _paneList[title]; }
+ }
+
+ /// <summary>
+ /// Add a <see cref="GraphPane"/> object to the <see cref="PaneList"/> collection at the end of the list.
+ /// </summary>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object to
+ /// be added</param>
+ /// <seealso cref="IList.Add"/>
+ public void Add( GraphPane pane )
+ {
+ _paneList.Add( pane );
+ }
+
+ /// <summary>
+ /// Call <see cref="GraphPane.AxisChange()"/> for all <see cref="GraphPane"/> objects in the
+ /// <see cref="PaneList"/> list.
+ /// </summary>
+ /// <remarks>
+ /// This overload of AxisChange just uses the default Graphics instance for the screen.
+ /// If you have a Graphics instance available from your Windows Form, you should use
+ /// the <see cref="AxisChange(Graphics)" /> overload instead.
+ /// </remarks>
+ public void AxisChange()
+ {
+ using ( Graphics g = Graphics.FromHwnd( IntPtr.Zero ) )
+ AxisChange( g );
+ }
+
+ /// <summary>
+ /// Call <see cref="GraphPane.AxisChange()"/> for all <see cref="GraphPane"/> objects in the
+ /// <see cref="PaneList"/> list.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public void AxisChange( Graphics g )
+ {
+ foreach ( GraphPane pane in _paneList )
+ pane.AxisChange( g );
+ }
+
+ /// <summary>
+ /// Redo the layout using the current size of the <see cref="PaneBase.Rect"/>,
+ /// and also handle resizing the
+ /// contents by calling <see cref="DoLayout(Graphics)"/>.
+ /// </summary>
+ /// <remarks>This method will use the pane layout that was specified by a call to
+ /// <see cref="SetLayout(Graphics,PaneLayout)"/>. If
+ /// <see cref="SetLayout(Graphics,PaneLayout)"/> has not previously been called,
+ /// it will default to <see cref="Default.PaneLayout"/>.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ public void ReSize( Graphics g )
+ {
+ ReSize( g, _rect );
+ }
+
+ /// <summary>
+ /// Change the size of the <see cref="PaneBase.Rect"/>, and also handle resizing the
+ /// contents by calling <see cref="DoLayout(Graphics)"/>.
+ /// </summary>
+ /// <remarks>This method will use the pane layout that was specified by a call to
+ /// <see cref="SetLayout(Graphics,PaneLayout)"/>. If
+ /// <see cref="SetLayout(Graphics,PaneLayout)"/> has not previously been called,
+ /// it will default to <see cref="Default.PaneLayout"/>.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect"></param>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ public override void ReSize( Graphics g, RectangleF rect )
+ {
+ _rect = rect;
+ DoLayout( g );
+ CommonScaleFactor();
+ }
+
+ /// <summary>
+ /// Method that forces the scale factor calculations
+ /// (via <see cref="PaneBase.CalcScaleFactor" />),
+ /// to give a common scale factor for all <see cref="GraphPane" /> objects in the
+ /// <see cref="PaneList" />.
+ /// </summary>
+ /// <remarks>
+ /// This will make it such that a given font size will result in the same output font
+ /// size for all <see cref="GraphPane" />'s. Note that this does not make the scale
+ /// factor for the <see cref="GraphPane" />'s the same as that of the
+ /// <see cref="MasterPane" />.
+ /// </remarks>
+ /// <seealso cref="IsCommonScaleFactor" />
+ public void CommonScaleFactor()
+ {
+ if ( _isCommonScaleFactor )
+ {
+ // Find the maximum scaleFactor of all the GraphPanes
+ float maxFactor = 0;
+ foreach ( GraphPane pane in PaneList )
+ {
+ pane.BaseDimension = PaneBase.Default.BaseDimension;
+ float scaleFactor = pane.CalcScaleFactor();
+ maxFactor = scaleFactor > maxFactor ? scaleFactor : maxFactor;
+ }
+
+ // Now, calculate the base dimension
+ foreach ( GraphPane pane in PaneList )
+ {
+ float scaleFactor = pane.CalcScaleFactor();
+ pane.BaseDimension *= scaleFactor / maxFactor;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Render all the <see cref="GraphPane"/> objects in the <see cref="PaneList"/> to the
+ /// specified graphics device.
+ /// </summary>
+ /// <remarks>This method should be part of the Paint() update process. Calling this routine
+ /// will redraw all
+ /// features of all the <see cref="GraphPane"/> items. No preparation is required other than
+ /// instantiated <see cref="GraphPane"/> objects that have been added to the list with the
+ /// <see cref="Add"/> method.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public override void Draw( Graphics g )
+ {
+ // Save current AntiAlias mode
+ SmoothingMode sModeSave = g.SmoothingMode;
+ TextRenderingHint sHintSave = g.TextRenderingHint;
+ CompositingQuality sCompQual = g.CompositingQuality;
+ InterpolationMode sInterpMode = g.InterpolationMode;
+
+ SetAntiAliasMode( g, _isAntiAlias );
+
+ // Draw the pane border & background fill, the title, and the GraphObj objects that lie at
+ // ZOrder.GBehindAll
+ base.Draw( g );
+
+ if ( _rect.Width <= 1 || _rect.Height <= 1 )
+ return;
+
+ float scaleFactor = CalcScaleFactor();
+
+ // Clip everything to the rect
+ g.SetClip( _rect );
+
+ // For the MasterPane, All GraphItems go behind the GraphPanes, except those that
+ // are explicity declared as ZOrder.AInFront
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.G_BehindChartFill );
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.E_BehindCurves );
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.D_BehindAxis );
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.C_BehindChartBorder );
+
+ // Reset the clipping
+ g.ResetClip();
+
+ foreach ( GraphPane pane in _paneList )
+ pane.Draw( g );
+
+ // Clip everything to the rect
+ g.SetClip( _rect );
+
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.B_BehindLegend );
+
+ // Recalculate the legend rect, just in case it has not yet been done
+ // innerRect is the area for the GraphPane's
+ RectangleF innerRect = CalcClientRect( g, scaleFactor );
+ _legend.CalcRect( g, this, scaleFactor, ref innerRect );
+ //this.legend.SetLocation( this,
+
+ _legend.Draw( g, this, scaleFactor );
+
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.A_InFront );
+
+ // Reset the clipping
+ g.ResetClip();
+
+ // Restore original anti-alias mode
+ g.SmoothingMode = sModeSave;
+ g.TextRenderingHint = sHintSave;
+ g.CompositingQuality = sCompQual;
+ g.InterpolationMode = sInterpMode;
+
+ }
+
+ /// <summary>
+ /// Find the pane and the object within that pane that lies closest to the specified
+ /// mouse (screen) point.
+ /// </summary>
+ /// <remarks>
+ /// This method first finds the <see cref="GraphPane"/> within the list that contains
+ /// the specified mouse point. It then calls the <see cref="GraphPane.FindNearestObject"/>
+ /// method to determine which object, if any, was clicked. With the exception of the
+ /// <see paramref="pane"/>, all the parameters in this method are identical to those
+ /// in the <see cref="GraphPane.FindNearestObject"/> method.
+ /// If the mouse point lies within the <see cref="PaneBase.Rect"/> of any
+ /// <see cref="GraphPane"/> item, then that pane will be returned (otherwise it will be
+ /// null). Further, within the selected pane, if the mouse point is within the
+ /// bounding box of any of the items (or in the case
+ /// of <see cref="ArrowObj"/> and <see cref="CurveItem"/>, within
+ /// <see cref="GraphPane.Default.NearestTol"/> pixels), then the object will be returned.
+ /// You must check the type of the object to determine what object was
+ /// selected (for example, "if ( object is Legend ) ..."). The
+ /// <see paramref="index"/> parameter returns the index number of the item
+ /// within the selected object (such as the point number within a
+ /// <see cref="CurveItem"/> object.
+ /// </remarks>
+ /// <param name="mousePt">The screen point, in pixel coordinates.</param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that was clicked.</param>
+ /// <param name="nearestObj">A reference to the nearest object to the
+ /// specified screen point. This can be any of <see cref="Axis"/>,
+ /// <see cref="Legend"/>, <see cref="PaneBase.Title"/>,
+ /// <see cref="TextObj"/>, <see cref="ArrowObj"/>, or <see cref="CurveItem"/>.
+ /// Note: If the pane title is selected, then the <see cref="GraphPane"/> object
+ /// will be returned.
+ /// </param>
+ /// <param name="index">The index number of the item within the selected object
+ /// (where applicable). For example, for a <see cref="CurveItem"/> object,
+ /// <see paramref="index"/> will be the index number of the nearest data point,
+ /// accessible via <see cref="CurveItem.Points">CurveItem.Points[index]</see>.
+ /// index will be -1 if no data points are available.</param>
+ /// <returns>true if a <see cref="GraphPane"/> was found, false otherwise.</returns>
+ /// <seealso cref="GraphPane.FindNearestObject"/>
+ public bool FindNearestPaneObject( PointF mousePt, Graphics g, out GraphPane pane,
+ out object nearestObj, out int index )
+ {
+ pane = null;
+ nearestObj = null;
+ index = -1;
+
+ GraphObj saveGraphItem = null;
+ int saveIndex = -1;
+ float scaleFactor = CalcScaleFactor();
+
+ // See if the point is in a GraphObj
+ // If so, just save the object and index so we can see if other overlying objects were
+ // intersected as well.
+ if ( this.GraphObjList.FindPoint( mousePt, this, g, scaleFactor, out index ) )
+ {
+ saveGraphItem = this.GraphObjList[index];
+ saveIndex = index;
+
+ // If it's an "In-Front" item, then just return it
+ if ( saveGraphItem.ZOrder == ZOrder.A_InFront )
+ {
+ nearestObj = saveGraphItem;
+ index = saveIndex;
+ return true;
+ }
+ }
+
+ foreach ( GraphPane tPane in _paneList )
+ {
+ if ( tPane.Rect.Contains( mousePt ) )
+ {
+ pane = tPane;
+ return tPane.FindNearestObject( mousePt, g, out nearestObj, out index );
+ }
+ }
+
+ // If no items were found in the GraphPanes, then return the item found on the MasterPane (if any)
+ if ( saveGraphItem != null )
+ {
+ nearestObj = saveGraphItem;
+ index = saveIndex;
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Find the <see cref="GraphPane"/> within the <see cref="PaneList"/> that contains the
+ /// <see paramref="mousePt"/> within its <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <param name="mousePt">The mouse point location where you want to search</param>
+ /// <returns>A <see cref="GraphPane"/> object that contains the mouse point, or
+ /// null if no <see cref="GraphPane"/> was found.</returns>
+ public GraphPane FindPane( PointF mousePt )
+ {
+ foreach ( GraphPane pane in _paneList )
+ {
+ if ( pane.Rect.Contains( mousePt ) )
+ return pane;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Find the <see cref="GraphPane"/> within the <see cref="PaneList"/> that contains the
+ /// <see paramref="mousePt"/> within its <see cref="Chart.Rect"/>.
+ /// </summary>
+ /// <param name="mousePt">The mouse point location where you want to search</param>
+ /// <returns>A <see cref="GraphPane"/> object that contains the mouse point, or
+ /// null if no <see cref="GraphPane"/> was found.</returns>
+ public GraphPane FindChartRect( PointF mousePt )
+ {
+ foreach ( GraphPane pane in _paneList )
+ {
+ if ( pane.Chart._rect.Contains( mousePt ) )
+ return pane;
+ }
+
+ return null;
+ }
+
+ #endregion
+
+ #region Layout Methods
+
+ /// <overloads>The SetLayout() methods setup the desired layout of the
+ /// <see cref="GraphPane" /> objects within a <see cref="MasterPane" />. These functions
+ /// do not make any changes, they merely set the parameters so that future calls
+ /// to <see cref="PaneBase.ReSize" /> or <see cref="DoLayout(Graphics)" />
+ /// will use the desired layout.<br /><br />
+ /// The layout options include a set of "canned" layouts provided by the
+ /// <see cref="ZedGraph.PaneLayout" /> enumeration, options to just set a specific
+ /// number of rows and columns of panes (and all pane sizes are the same), and more
+ /// customized options of specifying the number or rows in each column or the number of
+ /// columns in each row, along with proportional values that determine the size of each
+ /// individual column or row.
+ /// </overloads>
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to a pre-defined layout configuration from a <see cref="PaneLayout" />
+ /// enumeration.
+ /// </summary>
+ /// <remarks>This method uses a <see cref="PaneLayout"/> enumeration to describe the type of layout
+ /// to be used. Overloads are available that provide other layout options</remarks>
+ /// <param name="paneLayout">A <see cref="PaneLayout"/> enumeration that describes how
+ /// the panes should be laid out within the <see cref="PaneBase.Rect"/>.</param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally created with a call to
+ /// the CreateGraphics() method of the Control or Form.
+ /// </param>
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ public void SetLayout( Graphics g, PaneLayout paneLayout )
+ {
+ InitLayout();
+
+ _paneLayout = paneLayout;
+
+ DoLayout( g );
+ }
+
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to a reasonable configuration.
+ /// </summary>
+ /// <remarks>This method explicitly specifies the number of rows and columns to use
+ /// in the layout, and all <see cref="GraphPane" /> objects will have the same size.
+ /// Overloads are available that provide other layout options</remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally created with a call to
+ /// the CreateGraphics() method of the Control or Form.
+ /// </param>
+ /// <param name="rows">The number of rows of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ /// <param name="columns">The number of columns of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ public void SetLayout( Graphics g, int rows, int columns )
+ {
+ InitLayout();
+
+ if ( rows < 1 )
+ rows = 1;
+ if ( columns < 1 )
+ columns = 1;
+
+ int[] countList = new int[rows];
+
+ for ( int i = 0; i < rows; i++ )
+ countList[i] = columns;
+
+ SetLayout( g, true, countList, null );
+ }
+
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to the specified configuration.
+ /// </summary>
+ /// <remarks>This method specifies the number of rows in each column, or the number of
+ /// columns in each row, allowing for irregular layouts. Overloads are available that
+ /// provide other layout options.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally created with a call to
+ /// the CreateGraphics() method of the Control or Form.
+ /// </param>
+ /// <param name="isColumnSpecified">Specifies whether the number of columns in each row, or
+ /// the number of rows in each column will be specified. A value of true indicates the
+ /// number of columns in each row are specified in <see paramref="countList"/>.</param>
+ /// <param name="countList">An integer array specifying either the number of columns in
+ /// each row or the number of rows in each column, depending on the value of
+ /// <see paramref="isColumnSpecified"/>.</param>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ public void SetLayout( Graphics g, bool isColumnSpecified, int[] countList )
+ {
+ SetLayout( g, isColumnSpecified, countList, null );
+ }
+
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to the specified configuration.
+ /// </summary>
+ /// <remarks>This method specifies the number of panes in each row or column, allowing for
+ /// irregular layouts.</remarks>
+ /// <remarks>This method specifies the number of rows in each column, or the number of
+ /// columns in each row, allowing for irregular layouts. Additionally, a
+ /// <see paramref="proportion" /> parameter is provided that allows varying column or
+ /// row sizes. Overloads for SetLayout() are available that provide other layout options.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally created with a call to
+ /// the CreateGraphics() method of the Control or Form.
+ /// </param>
+ /// <param name="isColumnSpecified">Specifies whether the number of columns in each row, or
+ /// the number of rows in each column will be specified. A value of true indicates the
+ /// number of columns in each row are specified in <see paramref="_countList"/>.</param>
+ /// <param name="countList">An integer array specifying either the number of columns in
+ /// each row or the number of rows in each column, depending on the value of
+ /// <see paramref="isColumnSpecified"/>.</param>
+ /// <param name="proportion">An array of float values specifying proportional sizes for each
+ /// row or column. Note that these proportions apply to the non-specified dimension -- that is,
+ /// if <see paramref="isColumnSpecified"/> is true, then these proportions apply to the row
+ /// heights, and if <see paramref="isColumnSpecified"/> is false, then these proportions apply
+ /// to the column widths. The values in this array are arbitrary floats -- the dimension of
+ /// any given row or column is that particular proportional value divided by the sum of all
+ /// the values. For example, let <see paramref="isColumnSpecified"/> be true, and
+ /// <see paramref="proportion"/> is an array with values of { 1.0, 2.0, 3.0 }. The sum of
+ /// those values is 6.0. Therefore, the first row is 1/6th of the available height, the
+ /// second row is 2/6th's of the available height, and the third row is 3/6th's of the
+ /// available height.
+ /// </param>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ public void SetLayout( Graphics g, bool isColumnSpecified, int[] countList, float[] proportion )
+ {
+ InitLayout();
+
+ // use defaults if the parameters are invalid
+ if ( countList != null && countList.Length > 0 )
+ {
+ _prop = new float[countList.Length];
+
+ // Sum up the total proportional factors
+ float sumProp = 0.0f;
+ for ( int i = 0; i < countList.Length; i++ )
+ {
+ _prop[i] = ( proportion == null || proportion.Length <= i || proportion[i] < 1e-10 ) ?
+ 1.0f : proportion[i];
+ sumProp += _prop[i];
+ }
+
+ // Make prop sum to 1.0
+ for ( int i = 0; i < countList.Length; i++ )
+ _prop[i] /= sumProp;
+
+ _isColumnSpecified = isColumnSpecified;
+ _countList = countList;
+
+ DoLayout( g );
+ }
+ }
+
+ /// <summary>
+ /// Modify the <see cref="GraphPane" /> <see cref="PaneBase.Rect" /> sizes of each
+ /// <see cref="GraphPane" /> such that they fit within the <see cref="MasterPane" />
+ /// in a pre-configured layout.
+ /// </summary>
+ /// <remarks>The <see cref="SetLayout(Graphics,PaneLayout)" /> method (and overloads) is
+ /// used for setting the layout configuration.</remarks>
+ /// <seealso cref="SetLayout(Graphics,PaneLayout)" />
+ /// <seealso cref="SetLayout(Graphics,int,int)" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[])" />
+ /// <seealso cref="SetLayout(Graphics,bool,int[],float[])" />
+ public void DoLayout( Graphics g )
+ {
+ if ( _countList != null )
+ DoLayout( g, _isColumnSpecified, _countList, _prop );
+ else
+ {
+ int count = _paneList.Count;
+ if ( count == 0 )
+ return;
+
+ int rows,
+ cols,
+ root = (int)( Math.Sqrt( (double)count ) + 0.9999999 );
+
+ //float[] widthList = new float[5];
+
+ switch ( _paneLayout )
+ {
+ case PaneLayout.ForceSquare:
+ rows = root;
+ cols = root;
+ DoLayout( g, rows, cols );
+ break;
+ case PaneLayout.SingleColumn:
+ rows = count;
+ cols = 1;
+ DoLayout( g, rows, cols );
+ break;
+ case PaneLayout.SingleRow:
+ rows = 1;
+ cols = count;
+ DoLayout( g, rows, cols );
+ break;
+ default:
+ case PaneLayout.SquareColPreferred:
+ rows = root;
+ cols = root;
+ if ( count <= root * ( root - 1 ) )
+ rows--;
+ DoLayout( g, rows, cols );
+ break;
+ case PaneLayout.SquareRowPreferred:
+ rows = root;
+ cols = root;
+ if ( count <= root * ( root - 1 ) )
+ cols--;
+ DoLayout( g, rows, cols );
+ break;
+ case PaneLayout.ExplicitCol12:
+ DoLayout( g, true, new int[2] { 1, 2 }, null );
+ break;
+ case PaneLayout.ExplicitCol21:
+ DoLayout( g, true, new int[2] { 2, 1 }, null );
+ break;
+ case PaneLayout.ExplicitCol23:
+ DoLayout( g, true, new int[2] { 2, 3 }, null );
+ break;
+ case PaneLayout.ExplicitCol32:
+ DoLayout( g, true, new int[2] { 3, 2 }, null );
+ break;
+ case PaneLayout.ExplicitRow12:
+ DoLayout( g, false, new int[2] { 1, 2 }, null );
+ break;
+ case PaneLayout.ExplicitRow21:
+ DoLayout( g, false, new int[2] { 2, 1 }, null );
+ break;
+ case PaneLayout.ExplicitRow23:
+ DoLayout( g, false, new int[2] { 2, 3 }, null );
+ break;
+ case PaneLayout.ExplicitRow32:
+ DoLayout( g, false, new int[2] { 3, 2 }, null );
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Internal method that applies a previously set layout with a specific
+ /// row and column count. This method is only called by
+ /// <see cref="DoLayout(Graphics)" />.
+ /// </summary>
+ internal void DoLayout( Graphics g, int rows, int columns )
+ {
+ if ( rows < 1 )
+ rows = 1;
+ if ( columns < 1 )
+ columns = 1;
+
+ int[] countList = new int[rows];
+
+ for ( int i = 0; i < rows; i++ )
+ countList[i] = columns;
+
+ DoLayout( g, true, countList, null );
+ }
+
+ /// <summary>
+ /// Internal method that applies a previously set layout with a rows per column or
+ /// columns per row configuration. This method is only called by
+ /// <see cref="DoLayout(Graphics)" />.
+ /// </summary>
+ internal void DoLayout( Graphics g, bool isColumnSpecified, int[] countList,
+ float[] proportion )
+ {
+
+ // calculate scaleFactor on "normal" pane size (BaseDimension)
+ float scaleFactor = CalcScaleFactor();
+
+ // innerRect is the area for the GraphPane's
+ RectangleF innerRect = CalcClientRect( g, scaleFactor );
+ _legend.CalcRect( g, this, scaleFactor, ref innerRect );
+
+ // scaled InnerGap is the area between the GraphPane.Rect's
+ float scaledInnerGap = (float)( _innerPaneGap * scaleFactor );
+
+ int iPane = 0;
+
+ if ( isColumnSpecified )
+ {
+ int rows = countList.Length;
+
+ float y = 0.0f;
+
+ for ( int rowNum = 0; rowNum < rows; rowNum++ )
+ {
+ float propFactor = _prop == null ? 1.0f / rows : _prop[rowNum];
+
+ float height = ( innerRect.Height - (float)( rows - 1 ) * scaledInnerGap ) *
+ propFactor;
+
+ int columns = countList[rowNum];
+ if ( columns <= 0 )
+ columns = 1;
+ float width = ( innerRect.Width - (float)( columns - 1 ) * scaledInnerGap ) /
+ (float)columns;
+
+ for ( int colNum = 0; colNum < columns; colNum++ )
+ {
+ if ( iPane >= _paneList.Count )
+ return;
+
+ this[iPane].Rect = new RectangleF(
+ innerRect.X + colNum * ( width + scaledInnerGap ),
+ innerRect.Y + y,
+ width,
+ height );
+ iPane++;
+ }
+
+ y += height + scaledInnerGap;
+ }
+ }
+ else
+ {
+ int columns = countList.Length;
+
+ float x = 0.0f;
+
+ for ( int colNum = 0; colNum < columns; colNum++ )
+ {
+ float propFactor = _prop == null ? 1.0f / columns : _prop[colNum];
+
+ float width = ( innerRect.Width - (float)( columns - 1 ) * scaledInnerGap ) *
+ propFactor;
+
+ int rows = countList[colNum];
+ if ( rows <= 0 )
+ rows = 1;
+ float height = ( innerRect.Height - (float)( rows - 1 ) * scaledInnerGap ) / (float)rows;
+
+ for ( int rowNum = 0; rowNum < rows; rowNum++ )
+ {
+ if ( iPane >= _paneList.Count )
+ return;
+
+ this[iPane].Rect = new RectangleF(
+ innerRect.X + x,
+ innerRect.Y + rowNum * ( height + scaledInnerGap ),
+ width,
+ height );
+ iPane++;
+ }
+
+ x += width + scaledInnerGap;
+ }
+ }
+ }
+
+ /*
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to a reasonable configuration.
+ /// </summary>
+ /// <remarks>This method explicitly specifies the number of rows and columns to use in the layout.
+ /// A more automatic overload, using a <see cref="PaneLayout"/> enumeration, is available.</remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rows">The number of rows of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ /// <param name="columns">The number of columns of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ public void DoPaneLayout( Graphics g, int rows, int columns )
+ {
+ // save the layout settings for future reference
+ _countList = null;
+ _rows = rows;
+ _columns = columns;
+
+ // calculate scaleFactor on "normal" pane size (BaseDimension)
+ float scaleFactor = this.CalcScaleFactor();
+
+ // innerRect is the area for the GraphPane's
+ RectangleF innerRect = CalcClientRect( g, scaleFactor );
+ _legend.CalcRect( g, this, scaleFactor, ref innerRect );
+
+ // scaled InnerGap is the area between the GraphPane.Rect's
+ float scaledInnerGap = (float)( _innerPaneGap * scaleFactor );
+
+ float width = ( innerRect.Width - (float)( columns - 1 ) * scaledInnerGap ) / (float)columns;
+ float height = ( innerRect.Height - (float)( rows - 1 ) * scaledInnerGap ) / (float)rows;
+
+ int i = 0;
+ foreach ( GraphPane pane in _paneList )
+ {
+ float rowNum = (float)( i / columns );
+ float colNum = (float)( i % columns );
+
+ pane.Rect = new RectangleF(
+ innerRect.X + colNum * ( width + scaledInnerGap ),
+ innerRect.Y + rowNum * ( height + scaledInnerGap ),
+ width,
+ height );
+
+ i++;
+ }
+ }
+ */
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/MinorGrid.cs b/ZedGraph/MinorGrid.cs
new file mode 100644
index 0000000..9584b08
--- /dev/null
+++ b/ZedGraph/MinorGrid.cs
@@ -0,0 +1,293 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that holds the specific properties for the minor grid.
+ /// </summary>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class MinorGrid : ICloneable, ISerializable
+ {
+ internal bool _isVisible;
+
+ internal float _dashOn,
+ _dashOff,
+ _penWidth;
+
+ internal Color _color;
+
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ public MinorGrid()
+ {
+ _dashOn = Default.DashOn;
+ _dashOff = Default.DashOff;
+ _penWidth = Default.PenWidth;
+ _isVisible = Default.IsVisible;
+ _color = Default.Color;
+ }
+
+ /// <summary>
+ /// Copy constructor
+ /// </summary>
+ /// <param name="rhs">The source <see cref="MinorGrid" /> to be copied.</param>
+ public MinorGrid( MinorGrid rhs )
+ {
+ _dashOn = rhs._dashOn;
+ _dashOff = rhs._dashOff;
+ _penWidth = rhs._penWidth;
+
+ _isVisible = rhs._isVisible;
+
+ _color = rhs._color;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public MinorGrid Clone()
+ {
+ return new MinorGrid( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a value that determines if the major <see cref="Axis"/> gridlines
+ /// (at each labeled value) will be visible
+ /// </summary>
+ /// <value>true to show the gridlines, false otherwise</value>
+ /// <seealso cref="Default.IsVisible">Default.IsShowGrid</seealso>.
+ /// <seealso cref="Color"/>
+ /// <seealso cref="PenWidth"/>
+ /// <seealso cref="DashOn"/>
+ /// <seealso cref="DashOff"/>
+ /// <seealso cref="IsVisible"/>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ /// <summary>
+ /// The "Dash On" mode for drawing the grid.
+ /// </summary>
+ /// <remarks>
+ /// This is the distance,
+ /// in points (1/72 inch), of the dash segments that make up the dashed grid lines.
+ /// </remarks>
+ /// <value>The dash on length is defined in points (1/72 inch)</value>
+ /// <seealso cref="DashOff"/>
+ /// <seealso cref="IsVisible"/>
+ /// <seealso cref="Default.DashOn"/>.
+ public float DashOn
+ {
+ get { return _dashOn; }
+ set { _dashOn = value; }
+ }
+ /// <summary>
+ /// The "Dash Off" mode for drawing the grid.
+ /// </summary>
+ /// <remarks>
+ /// This is the distance,
+ /// in points (1/72 inch), of the spaces between the dash segments that make up
+ /// the dashed grid lines.
+ /// </remarks>
+ /// <value>The dash off length is defined in points (1/72 inch)</value>
+ /// <seealso cref="DashOn"/>
+ /// <seealso cref="IsVisible"/>
+ /// <seealso cref="Default.DashOff"/>.
+ public float DashOff
+ {
+ get { return _dashOff; }
+ set { _dashOff = value; }
+ }
+ /// <summary>
+ /// The pen width used for drawing the grid lines.
+ /// </summary>
+ /// <value>The grid pen width is defined in points (1/72 inch)</value>
+ /// <seealso cref="IsVisible"/>
+ /// <seealso cref="Default.PenWidth"/>.
+ /// <seealso cref="Color"/>
+ public float PenWidth
+ {
+ get { return _penWidth; }
+ set { _penWidth = value; }
+ }
+ /// <summary>
+ /// The color to use for drawing this <see cref="Axis"/> grid.
+ /// </summary>
+ /// <value> The color is defined using the
+ /// <see cref="System.Drawing.Color"/> class</value>
+ /// <seealso cref="Default.Color"/>.
+ /// <seealso cref="PenWidth"/>
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected MinorGrid( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _isVisible = info.GetBoolean( "isVisible" );
+
+ _dashOn = info.GetSingle( "dashOn" );
+ _dashOff = info.GetSingle( "dashOff" );
+ _penWidth = info.GetSingle( "penWidth" );
+
+ _color = (Color)info.GetValue( "color", typeof( Color ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "isVisible", _isVisible );
+
+ info.AddValue( "dashOn", _dashOn );
+ info.AddValue( "dashOff", _dashOff );
+ info.AddValue( "penWidth", _penWidth );
+
+ info.AddValue( "color", _color );
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="MinorGrid"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default "dash on" size for drawing the <see cref="Axis"/> minor grid
+ /// (<see cref="MinorGrid.DashOn"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float DashOn = 1.0F;
+ /// <summary>
+ /// The default "dash off" size for drawing the <see cref="Axis"/> minor grid
+ /// (<see cref="MinorGrid.DashOff"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float DashOff = 10.0F;
+ /// <summary>
+ /// The default pen width for drawing the <see cref="Axis"/> minor grid
+ /// (<see cref="MinorGrid.PenWidth"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The default color for the <see cref="Axis"/> minor grid lines
+ /// (<see cref="MinorGrid.Color"/> property). This color only affects the
+ /// minor grid lines.
+ /// </summary>
+ public static Color Color = Color.Gray;
+
+ /// <summary>
+ /// The default display mode for the <see cref="Axis"/> minor grid lines
+ /// (<see cref="MinorGrid.IsVisible"/> property). true
+ /// to show the minor grid lines, false to hide them.
+ /// </summary>
+ public static bool IsVisible = false;
+
+ }
+
+ #endregion
+
+ #region Methods
+
+ internal void Draw( Graphics g, Pen pen, float pixVal, float topPix )
+ {
+ // draw the minor grid
+ if ( _isVisible )
+ g.DrawLine( pen, pixVal, 0.0F, pixVal, topPix );
+ }
+
+ internal Pen GetPen( GraphPane pane, float scaleFactor )
+ {
+ Pen pen = new Pen( _color,
+ pane.ScaledPenWidth( _penWidth, scaleFactor ) );
+
+ if ( _dashOff > 1e-10 && _dashOn > 1e-10 )
+ {
+ pen.DashStyle = DashStyle.Custom;
+ float[] pattern = new float[2];
+ pattern[0] = _dashOn;
+ pattern[1] = _dashOff;
+ pen.DashPattern = pattern;
+ }
+
+ return pen;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/MinorTic.cs b/ZedGraph/MinorTic.cs
new file mode 100644
index 0000000..8b8c19d
--- /dev/null
+++ b/ZedGraph/MinorTic.cs
@@ -0,0 +1,500 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Class that holds the specific properties for the minor tics.
+ /// </summary>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class MinorTic : ICloneable, ISerializable
+ {
+ internal bool _isOutside,
+ _isInside,
+ _isOpposite,
+ _isCrossOutside,
+ _isCrossInside;
+
+ internal float _penWidth,
+ _size;
+
+ internal Color _color;
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public MinorTic()
+ {
+ _size = Default.Size;
+ _color = Default.Color;
+ _penWidth = Default.PenWidth;
+
+ this.IsOutside = Default.IsOutside;
+ this.IsInside = Default.IsInside;
+ this.IsOpposite = Default.IsOpposite;
+ _isCrossOutside = Default.IsCrossOutside;
+ _isCrossInside = Default.IsCrossInside;
+ }
+
+ /// <summary>
+ /// Copy constructor.
+ /// </summary>
+ /// <param name="rhs">The <see cref="MinorTic" /> that is to be copied.</param>
+ public MinorTic( MinorTic rhs )
+ {
+ _size = rhs._size;
+ _color = rhs._color;
+ _penWidth = rhs._penWidth;
+
+ this.IsOutside = rhs.IsOutside;
+ this.IsInside = rhs.IsInside;
+ this.IsOpposite = rhs.IsOpposite;
+ _isCrossOutside = rhs._isCrossOutside;
+ _isCrossInside = rhs._isCrossInside;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public MinorTic Clone()
+ {
+ return new MinorTic( this );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// The color to use for drawing the tics of this class instance
+ /// </summary>
+ /// <value> The color is defined using the
+ /// <see cref="System.Drawing.Color"/> class</value>
+ /// <seealso cref="Default.Color"/>.
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="Axis.IsVisible"/>
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; }
+ }
+
+ /// <summary>
+ /// The length of the major tic marks.
+ /// </summary>
+ /// <remarks>
+ /// This length will be scaled
+ /// according to the <see cref="PaneBase.CalcScaleFactor"/> for the
+ /// <see cref="GraphPane"/>
+ /// </remarks>
+ /// <value>The tic size is measured in points (1/72 inch)</value>
+ /// <seealso cref="Default.Size"/>.
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="Axis.IsVisible"/>
+ /// <seealso cref="Color"/>
+ public float Size
+ {
+ get { return _size; }
+ set { _size = value; }
+ }
+ /// <summary>
+ /// Calculate the scaled tic size for this <see cref="Axis"/>
+ /// </summary>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The scaled tic size, in points (1/72 inch)</returns>
+ /// <seealso cref="Size"/>
+ /// <seealso cref="Scale.FontSpec"/>
+ /// <seealso cref="PaneBase.CalcScaleFactor"/>
+ public float ScaledTic( float scaleFactor )
+ {
+ return (float)( _size * scaleFactor );
+ }
+
+ /// <summary>
+ /// This is convenience property sets the status of all the different
+ /// tic properties in this instance to the same value. true to activate all tics,
+ /// false to clear all tics.
+ /// </summary>
+ /// <remarks>
+ /// This setting does not persist. That is, you can clear all the tics with
+ /// <see cref="IsAllTics" /> = false, then activate them individually (example:
+ /// <see cref="IsOutside" /> = true).
+ /// </remarks>
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="IsInside"/>
+ /// <seealso cref="IsOpposite"/>
+ /// <seealso cref="IsCrossInside"/>
+ /// <seealso cref="IsCrossOutside"/>
+ public bool IsAllTics
+ {
+ set
+ {
+ this.IsOutside = value;
+ this.IsInside = value;
+ this.IsOpposite = value;
+ _isCrossOutside = value;
+ _isCrossInside = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines whether or not the minor outside tic marks
+ /// are shown.
+ /// </summary>
+ /// <remarks>
+ /// These are the tic marks on the outside of the <see cref="Axis"/> border.
+ /// The minor tic spacing is controlled by <see cref="Scale.MinorStep"/>.
+ /// </remarks>
+ /// <value>true to show the minor outside tic marks, false otherwise</value>
+ /// <seealso cref="Default.IsOutside"/>.
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="IsInside"/>
+ /// <seealso cref="IsOpposite"/>
+ /// <seealso cref="IsCrossInside"/>
+ /// <seealso cref="IsCrossOutside"/>
+ public bool IsOutside
+ {
+ get { return _isOutside; }
+ set { _isOutside = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines whether or not the major inside tic marks
+ /// are shown.
+ /// </summary>
+ /// <remarks>
+ /// These are the tic marks on the inside of the <see cref="Axis"/> border.
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major inside tic marks, false otherwise</value>
+ /// <seealso cref="Default.IsInside"/>.
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="IsInside"/>
+ /// <seealso cref="IsOpposite"/>
+ /// <seealso cref="IsCrossInside"/>
+ /// <seealso cref="IsCrossOutside"/>
+ public bool IsInside
+ {
+ get { return _isInside; }
+ set { _isInside = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines whether or not the major opposite tic marks
+ /// are shown.
+ /// </summary>
+ /// <remarks>
+ /// These are the tic marks on the inside of the <see cref="Axis"/> border on
+ /// the opposite side from the axis.
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major opposite tic marks, false otherwise</value>
+ /// <seealso cref="Default.IsOpposite"/>.
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="IsInside"/>
+ /// <seealso cref="IsOpposite"/>
+ /// <seealso cref="IsCrossInside"/>
+ /// <seealso cref="IsCrossOutside"/>
+ public bool IsOpposite
+ {
+ get { return _isOpposite; }
+ set { _isOpposite = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the display mode for the <see cref="Axis"/> major outside
+ /// "cross" tic marks.
+ /// </summary>
+ /// <remarks>
+ /// The "cross" tics are a special, additional set of tic marks that
+ /// always appear on the actual axis, even if it has been shifted due
+ /// to the <see cref="Axis.Cross" /> setting. The other tic marks are always
+ /// fixed to the edges of the <see cref="Chart.Rect"/>. The cross tics
+ /// are normally not displayed, since, if <see cref="Axis.CrossAuto" /> is true,
+ /// they will exactly overlay the "normal" and "inside" tics. If
+ /// <see cref="Axis.CrossAuto"/> is false, then you will most likely want to
+ /// enable the cross tics.
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major cross tic marks, false otherwise</value>
+ public bool IsCrossOutside
+ {
+ get { return _isCrossOutside; }
+ set { _isCrossOutside = value; }
+ }
+ /// <summary>
+ /// Gets or sets the display mode for the <see cref="Axis"/> major inside
+ /// "cross" tic marks.
+ /// </summary>
+ /// <remarks>
+ /// The "cross" tics are a special, additional set of tic marks that
+ /// always appear on the actual axis, even if it has been shifted due
+ /// to the <see cref="Axis.Cross" /> setting. The other tic marks are always
+ /// fixed to the edges of the <see cref="Chart.Rect"/>. The cross tics
+ /// are normally not displayed, since, if <see cref="Axis.CrossAuto" /> is true,
+ /// they will exactly overlay the "normal" and "inside" tics. If
+ /// <see cref="Axis.CrossAuto"/> is false, then you will most likely want to
+ /// enable the cross tics.
+ /// The major tic spacing is controlled by <see cref="Scale.MajorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major cross tic marks, false otherwise</value>
+ public bool IsCrossInside
+ {
+ get { return _isCrossInside; }
+ set { _isCrossInside = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the pen width to be used when drawing the tic marks for
+ /// this <see cref="Axis"/>
+ /// </summary>
+ /// <value>The pen width is defined in points (1/72 inch)</value>
+ /// <seealso cref="Default.PenWidth"/>.
+ /// <seealso cref="IsOutside"/>
+ /// <seealso cref="Color"/>
+ public float PenWidth
+ {
+ get { return _penWidth; }
+ set { _penWidth = value; }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected MinorTic( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _color = (Color) info.GetValue( "color", typeof( Color ) );
+ _size = info.GetSingle( "size" );
+ _penWidth = info.GetSingle( "penWidth" );
+
+ IsOutside = info.GetBoolean( "IsOutside" );
+ IsInside = info.GetBoolean( "IsInside" );
+ IsOpposite = info.GetBoolean( "IsOpposite" );
+ _isCrossOutside = info.GetBoolean( "isCrossOutside" );
+ _isCrossInside = info.GetBoolean( "isCrossInside" );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "color", _color );
+ info.AddValue( "size", _size );
+ info.AddValue( "penWidth", _penWidth );
+
+ info.AddValue( "IsOutside", IsOutside );
+ info.AddValue( "IsInside", IsInside );
+ info.AddValue( "IsOpposite", IsOpposite );
+ info.AddValue( "isCrossOutside", _isCrossOutside );
+ info.AddValue( "isCrossInside", _isCrossInside );
+
+ }
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="MinorTic"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default size for the <see cref="Axis"/> minor tic marks.
+ /// (<see cref="MinorTic.Size"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float Size = 2.5F;
+ /// <summary>
+ /// The default pen width for drawing the <see cref="Axis"/> tic marks.
+ /// (<see cref="MinorTic.PenWidth"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The display mode for the <see cref="Axis"/> minor outside tic marks
+ /// (<see cref="MinorTic.IsOutside"/> property).
+ /// The minor tic spacing is controlled by <see cref="Scale.MinorStep"/>.
+ /// </summary>
+ /// <value>true to show the minor tic marks (outside the axis),
+ /// false otherwise</value>
+ public static bool IsOutside = true;
+ /// <summary>
+ /// The display mode for the <see cref="Axis"/> minor inside tic marks
+ /// (<see cref="MinorTic.IsInside"/> property).
+ /// The minor tic spacing is controlled by <see cref="Scale.MinorStep"/>.
+ /// </summary>
+ /// <value>true to show the minor tic marks (inside the axis),
+ /// false otherwise</value>
+ public static bool IsInside = true;
+ /// <summary>
+ /// The display mode for the <see cref="Axis"/> minor opposite tic marks
+ /// (<see cref="MinorTic.IsOpposite"/> property).
+ /// The minor tic spacing is controlled by <see cref="Scale.MinorStep"/>.
+ /// </summary>
+ /// <value>true to show the minor tic marks
+ /// (inside the axis on the opposite side),
+ /// false otherwise</value>
+ public static bool IsOpposite = true;
+
+ /// <summary>
+ /// The default display mode for the <see cref="Axis"/> minor outside
+ /// "cross" tic marks (<see cref="MinorTic.IsCrossOutside"/> property).
+ /// </summary>
+ /// <remarks>
+ /// The "cross" tics are a special, additional set of tic marks that
+ /// always appear on the actual axis, even if it has been shifted due
+ /// to the <see cref="Axis.Cross" /> setting. The other tic marks are always
+ /// fixed to the edges of the <see cref="Chart.Rect"/>. The cross tics
+ /// are normally not displayed, since, if <see cref="Axis.CrossAuto" /> is true,
+ /// they will exactly overlay the "normal" and "inside" tics. If
+ /// <see cref="Axis.CrossAuto"/> is false, then you will most likely want to
+ /// enable the cross tics.
+ /// The minor tic spacing is controlled by <see cref="Scale.MinorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major cross tic marks, false otherwise</value>
+ public static bool IsCrossOutside = false;
+ /// <summary>
+ /// The default display mode for the <see cref="Axis"/> minor inside
+ /// "cross" tic marks (<see cref="MinorTic.IsCrossInside"/> property).
+ /// </summary>
+ /// <remarks>
+ /// The "cross" tics are a special, additional set of tic marks that
+ /// always appear on the actual axis, even if it has been shifted due
+ /// to the <see cref="Axis.Cross" /> setting. The other tic marks are always
+ /// fixed to the edges of the <see cref="Chart.Rect"/>. The cross tics
+ /// are normally not displayed, since, if <see cref="Axis.CrossAuto" /> is true,
+ /// they will exactly overlay the "normal" and "inside" tics. If
+ /// <see cref="Axis.CrossAuto"/> is false, then you will most likely want to
+ /// enable the cross tics.
+ /// The major tic spacing is controlled by <see cref="Scale.MinorStep"/>.
+ /// </remarks>
+ /// <value>true to show the major cross tic marks, false otherwise</value>
+ public static bool IsCrossInside = false;
+
+ /// <summary>
+ /// The default color for minor tics (<see cref="MinorTic.Color"/> property).
+ /// </summary>
+ public static Color Color = Color.Black;
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Draw a tic mark at the specified single position. This includes the inner, outer,
+ /// cross and opposite tic marks as required.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pen">Graphic <see cref="Pen"/> with which to draw the tic mark.</param>
+ /// <param name="pixVal">The pixel location of the tic mark on this
+ /// <see cref="Axis"/></param>
+ /// <param name="topPix">The pixel value of the top of the axis border</param>
+ /// <param name="shift">The number of pixels to shift this axis, based on the
+ /// value of <see cref="Axis.Cross"/>. A positive value is into the ChartRect relative to
+ /// the default axis position.</param>
+ /// <param name="scaledTic">The scaled size of a minor tic, in pixel units</param>
+ internal void Draw( Graphics g, GraphPane pane, Pen pen, float pixVal, float topPix,
+ float shift, float scaledTic )
+ {
+ // draw the outside tic
+ if ( this.IsOutside )
+ g.DrawLine( pen, pixVal, shift, pixVal, shift + scaledTic );
+
+ // draw the cross tic
+ if ( _isCrossOutside )
+ g.DrawLine( pen, pixVal, 0.0f, pixVal, scaledTic );
+
+ // draw the inside tic
+ if ( this.IsInside )
+ g.DrawLine( pen, pixVal, shift, pixVal, shift - scaledTic );
+
+ // draw the inside cross tic
+ if ( _isCrossInside )
+ g.DrawLine( pen, pixVal, 0.0f, pixVal, -scaledTic );
+
+ // draw the opposite tic
+ if ( this.IsOpposite )
+ g.DrawLine( pen, pixVal, topPix, pixVal, topPix + scaledTic );
+ }
+
+ internal Pen GetPen( GraphPane pane, float scaleFactor )
+ {
+ return new Pen( _color, pane.ScaledPenWidth( _penWidth, scaleFactor ) );
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/NoDupePointList.cs b/ZedGraph/NoDupePointList.cs
new file mode 100644
index 0000000..ea359af
--- /dev/null
+++ b/ZedGraph/NoDupePointList.cs
@@ -0,0 +1,358 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A simple storage struct to maintain an individual sampling of data. This only
+ /// contains two data values in order to reduce to memory load for large datasets.
+ /// (e.g., no Tag or Z property)
+ /// </summary>
+ public struct DataPoint
+ {
+ /// <summary>
+ /// The X value for the point, stored as a double type.
+ /// </summary>
+ public double X;
+ /// <summary>
+ /// The Y value for the point, stored as a double type.
+ /// </summary>
+ public double Y;
+ }
+
+ /// <summary>
+ /// A collection class to maintain a set of samples.
+ /// </summary>
+ /// <remarks>This type, intended for very
+ /// large datasets, will reduce the number of points displayed by eliminating
+ /// individual points that overlay (at the same pixel location) on the graph.
+ /// Note that this type probably does not make sense for line plots, but is intended
+ /// primarily for scatter plots.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.5 $ $Date: 2007-06-02 06:56:03 $ </version>
+ [Serializable]
+ public class NoDupePointList : List<DataPoint>, IPointList, IPointListEdit
+ {
+ /// <summary>
+ /// Protected field that stores a value indicating whether or not the data have been filtered.
+ /// If the data have not been filtered, then <see cref="Count" /> will be equal to
+ /// <see cref="TotalCount" />. Use the public property <see cref="IsFiltered" /> to
+ /// access this value.
+ /// </summary>
+ protected bool _isFiltered;
+ /// <summary>
+ /// Protected field that stores the number of data points after filtering (e.g.,
+ /// <see cref="FilterData" /> has been called). The <see cref="Count" /> property
+ /// returns the total count for an unfiltered dataset, or <see cref="_filteredCount" />
+ /// for a dataset that has been filtered.
+ /// </summary>
+ protected int _filteredCount;
+ /// <summary>
+ /// Protected array of indices for all the points that are currently visible. This only
+ /// applies if <see cref="IsFiltered" /> is true.
+ /// </summary>
+ protected int[] _visibleIndicies;
+
+
+ /// <summary>
+ /// Protected field that stores a value that determines how close a point must be to a prior
+ /// neighbor in order to be filtered out. Use the public property <see cref="FilterMode" />
+ /// to access this value.
+ /// </summary>
+ protected int _filterMode;
+
+
+ /// <summary>
+ /// Gets or sets a value that determines how close a point must be to a prior
+ /// neighbor in order to be filtered out.
+ /// </summary>
+ /// <remarks>
+ /// A value of 0 indicates that subsequent
+ /// points must coincide exactly at the same pixel location. A value of 1 or more
+ /// indicates that number of pixels distance from a prior point that will cause
+ /// a new point to be filtered out. For example, a value of 2 means that, once
+ /// a particular pixel location is taken, any subsequent point that lies within 2
+ /// pixels of that location will be filtered out.
+ /// </remarks>
+ public int FilterMode
+ {
+ get { return _filterMode; }
+ set { _filterMode = value; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether or not the data have been filtered. If the data
+ /// have not been filtered, then <see cref="Count" /> will be equal to
+ /// <see cref="TotalCount" />.
+ /// </summary>
+ public bool IsFiltered
+ {
+ get { return _isFiltered; }
+ }
+
+ /// <summary>
+ /// Indexer: get the DataPoint instance at the specified ordinal position in the list
+ /// </summary>
+ /// <remarks>
+ /// This method will throw an exception if the index is out of range. This can happen
+ /// if the index is less than the number of filtered values, or if data points are
+ /// removed from a filtered dataset with updating the filter (by calling
+ /// <see cref="FilterData" />).
+ /// </remarks>
+ /// <param name="index">The ordinal position in the list of points</param>
+ /// <returns>Returns a <see cref="PointPair" /> instance. The <see cref="PointPair.Z" />
+ /// and <see cref="PointPair.Tag" /> properties will be defaulted to
+ /// <see cref="PointPairBase.Missing" /> and null, respectively.
+ /// </returns>
+ public new PointPair this[int index]
+ {
+ get
+ {
+ int j = index;
+ if ( _isFiltered )
+ j = _visibleIndicies[index];
+
+ DataPoint dp = base[j];
+ PointPair pt = new PointPair( dp.X, dp.Y );
+ return pt;
+ }
+ set
+ {
+ int j = index;
+ if ( _isFiltered )
+ j = _visibleIndicies[index];
+
+ DataPoint dp;
+ dp.X = value.X;
+ dp.Y = value.Y;
+ base[j] = dp;
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of active samples in the collection. This is the number of
+ /// samples that are non-duplicates. See the <see cref="TotalCount" /> property
+ /// to get the total number of samples in the list.
+ /// </summary>
+ public new int Count
+ {
+ get
+ {
+ if ( !_isFiltered )
+ return base.Count;
+ else
+ return _filteredCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets the total number of samples in the collection. See the <see cref="Count" />
+ /// property to get the number of active (non-duplicate) samples in the list.
+ /// </summary>
+ public int TotalCount
+ {
+ get { return base.Count; }
+ }
+
+ /// <summary>
+ /// Append a data point to the collection
+ /// </summary>
+ /// <param name="pt">The <see cref="PointPair" /> value to append</param>
+ public void Add( PointPair pt )
+ {
+ DataPoint dp = new DataPoint();
+ dp.X = pt.X;
+ dp.Y = pt.Y;
+ Add( dp );
+ }
+
+
+ /// <summary>
+ /// Append a point to the collection
+ /// </summary>
+ /// <param name="x">The x value of the point to append</param>
+ /// <param name="y">The y value of the point to append</param>
+ public void Add( double x, double y )
+ {
+ DataPoint dp = new DataPoint();
+ dp.X = x;
+ dp.Y = y;
+ Add( dp );
+ }
+
+
+ // generic Clone: just call the typesafe version
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// typesafe clone method
+ /// </summary>
+ /// <returns>A new cloned NoDupePointList. This returns a copy of the structure,
+ /// but it does not duplicate the data (it just keeps a reference to the original)
+ /// </returns>
+ public NoDupePointList Clone()
+ {
+ return new NoDupePointList( this );
+ }
+
+ /// <summary>
+ /// default constructor
+ /// </summary>
+ public NoDupePointList()
+ {
+ _isFiltered = false;
+ _filteredCount = 0;
+ _visibleIndicies = null;
+ _filterMode = 0;
+ }
+
+ /// <summary>
+ /// copy constructor -- this returns a copy of the structure,
+ /// but it does not duplicate the data (it just keeps a reference to the original)
+ /// </summary>
+ /// <param name="rhs">The NoDupePointList to be copied</param>
+ public NoDupePointList( NoDupePointList rhs )
+ {
+ int count = rhs.TotalCount;
+ for ( int i = 0; i < count; i++ )
+ Add( rhs.GetDataPointAt( i ) );
+
+ _filteredCount = rhs._filteredCount;
+ _isFiltered = rhs._isFiltered;
+ _filterMode = rhs._filterMode;
+
+ if ( rhs._visibleIndicies != null )
+ _visibleIndicies = (int[]) rhs._visibleIndicies.Clone();
+ else
+ _visibleIndicies = null;
+ }
+
+ /// <summary>
+ /// Protected method to access the internal DataPoint collection, without any
+ /// translation to a PointPair.
+ /// </summary>
+ /// <param name="index">The ordinal position of the DataPoint of interest</param>
+ protected DataPoint GetDataPointAt( int index )
+ {
+ return base[index];
+ }
+
+ /// <summary>
+ /// Clears any filtering previously done by a call to <see cref="FilterData" />.
+ /// After calling this method, all data points will be visible, and
+ /// <see cref="Count" /> will be equal to <see cref="TotalCount" />.
+ /// </summary>
+ public void ClearFilter()
+ {
+ _isFiltered = false;
+ _filteredCount = 0;
+ }
+
+ /// <summary>
+ /// Go through the collection, and hide (filter out) any points that fall on the
+ /// same pixel location as a previously included point.
+ /// </summary>
+ /// <remarks>
+ /// This method does not delete any points, it just temporarily hides them until
+ /// the next call to <see cref="FilterData" /> or <see cref="ClearFilter" />.
+ /// You should call <see cref="FilterData" /> once your collection of points has
+ /// been constructed. You may need to call <see cref="FilterData" /> again if
+ /// you add points, or if the chart rect changes size (by resizing, printing,
+ /// image save, etc.), or if the scale range changes.
+ /// You must call <see cref="GraphPane.AxisChange()" /> before calling
+ /// this method so that the <see cref="Chart.Rect">GraphPane.Chart.Rect</see>
+ /// and the scale ranges are valid. This method is not valid for
+ /// ordinal axes (but ordinal axes don't make sense for very large datasets
+ /// anyway).
+ /// </remarks>
+ /// <param name="pane">The <see cref="GraphPane" /> into which the data
+ /// will be plotted. </param>
+ /// <param name="yAxis">The <see cref="Axis" /> class to be used in the Y direction
+ /// for plotting these data. This can be a <see cref="YAxis" /> or a
+ /// <see cref="Y2Axis" />, and can be a primary or secondary axis (if multiple Y or Y2
+ /// axes are being used).
+ /// </param>
+ /// <param name="xAxis">The <see cref="Axis" /> class to be used in the X direction
+ /// for plotting these data. This can be an <see cref="XAxis" /> or a
+ /// <see cref="X2Axis" />.
+ /// </param>
+ public void FilterData( GraphPane pane, Axis xAxis, Axis yAxis )
+ {
+ if ( _visibleIndicies == null || _visibleIndicies.Length < base.Count )
+ _visibleIndicies = new int[base.Count];
+
+ _filteredCount = 0;
+ _isFiltered = true;
+
+ int width = (int)pane.Chart.Rect.Width;
+ int height = (int)pane.Chart.Rect.Height;
+ if ( width <= 0 || height <= 0 )
+ throw new IndexOutOfRangeException( "Error in FilterData: Chart rect not valid" );
+
+ bool[,] usedArray = new bool[width, height];
+ for ( int i = 0; i < width; i++ )
+ for ( int j = 0; j < height; j++ )
+ usedArray[i, j] = false;
+
+ xAxis.Scale.SetupScaleData( pane, xAxis );
+ yAxis.Scale.SetupScaleData( pane, yAxis );
+
+ int n = _filterMode < 0 ? 0 : _filterMode;
+ int left = (int)pane.Chart.Rect.Left;
+ int top = (int)pane.Chart.Rect.Top;
+
+ for ( int i=0; i<base.Count; i++ )
+ {
+ DataPoint dp = base[i];
+ int x = (int)( xAxis.Scale.Transform( dp.X ) + 0.5 ) - left;
+ int y = (int)( yAxis.Scale.Transform( dp.Y ) + 0.5 ) - top;
+
+ if ( x >= 0 && x < width && y >= 0 && y < height )
+ {
+ bool used = false;
+ if ( n <= 0 )
+ used = usedArray[x, y];
+ else
+ {
+ for ( int ix = x - n; ix <= x + n; ix++ )
+ for ( int iy = y - n; iy <= y + n; iy++ )
+ used |= ( ix >= 0 && ix < width && iy >= 0 && iy < height && usedArray[ix, iy] );
+ }
+
+ if ( !used )
+ {
+ usedArray[x, y] = true;
+ _visibleIndicies[_filteredCount] = i;
+ _filteredCount++;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ZedGraph/OHLCBar.cs b/ZedGraph/OHLCBar.cs
new file mode 100644
index 0000000..0f3cd99
--- /dev/null
+++ b/ZedGraph/OHLCBar.cs
@@ -0,0 +1,435 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This class handles the drawing of the curve <see cref="OHLCBar"/> objects.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.5 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ public class OHLCBar : LineBase, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores the visibility of the <see cref="OHLCBar"/> open and
+ /// close line segments ("wings"). Use the public
+ /// property <see cref="IsOpenCloseVisible"/> to access this value. If this value is
+ /// false, the wings will not be shown.
+ /// </summary>
+ protected bool _isOpenCloseVisible;
+
+ /// <summary>
+ /// Private field that stores the total width for the Opening/Closing line
+ /// segments. Use the public property <see cref="Size"/> to access this value.
+ /// </summary>
+ protected float _size;
+
+ /// <summary>
+ /// Private field that determines if the <see cref="Size" /> property will be
+ /// calculated automatically based on the minimum axis scale step size between
+ /// bars. Use the public property <see cref="IsAutoSize" /> to access this value.
+ /// </summary>
+ protected Boolean _isAutoSize;
+
+ /// <summary>
+ /// The result of the autosize calculation, which is the size of the bars in
+ /// user scale units. This is converted to pixels at draw time.
+ /// </summary>
+ internal double _userScaleSize = 1.0;
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ZedGraph.OHLCBar"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ // Default Symbol properties
+ /// <summary>
+ /// The default width for the candlesticks (see <see cref="OHLCBar.Size" />),
+ /// in units of points.
+ /// </summary>
+ public static float Size = 12;
+ /// <summary>
+ /// The default display mode for symbols (<see cref="OHLCBar.IsOpenCloseVisible"/> property).
+ /// true to display symbols, false to hide them.
+ /// </summary>
+ public static bool IsOpenCloseVisible = true;
+
+ /// <summary>
+ /// The default value for the <see cref="ZedGraph.OHLCBar.IsAutoSize" /> property.
+ /// </summary>
+ public static Boolean IsAutoSize = true;
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a property that shows or hides the <see cref="OHLCBar"/> open/close "wings".
+ /// </summary>
+ /// <value>true to show the CandleStick wings, false to hide them</value>
+ /// <seealso cref="Default.IsOpenCloseVisible"/>
+ public bool IsOpenCloseVisible
+ {
+ get { return _isOpenCloseVisible; }
+ set { _isOpenCloseVisible = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the total width to be used for drawing the opening/closing line
+ /// segments ("wings") of the <see cref="OHLCBar" /> items. Units are points.
+ /// </summary>
+ /// <remarks>The size of the candlesticks can be set by this value, which
+ /// is then scaled according to the scaleFactor (see
+ /// <see cref="PaneBase.CalcScaleFactor"/>). Alternatively,
+ /// if <see cref="IsAutoSize"/> is true, the bar width will
+ /// be set according to the maximum available cluster width less
+ /// the cluster gap (see <see cref="BarSettings.GetClusterWidth"/>
+ /// and <see cref="BarSettings.MinClusterGap"/>). That is, if
+ /// <see cref="IsAutoSize"/> is true, then the value of
+ /// <see cref="Size"/> will be ignored. If you modify the value of Size,
+ /// then <see cref="IsAutoSize" /> will be automatically set to false.
+ /// </remarks>
+ /// <value>Size in points (1/72 inch)</value>
+ /// <seealso cref="Default.Size"/>
+ public float Size
+ {
+ get { return _size; }
+ set { _size = value; _isAutoSize = false; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the <see cref="Size" /> property will be
+ /// calculated automatically based on the minimum axis scale step size between
+ /// bars.
+ /// </summary>
+ public Boolean IsAutoSize
+ {
+ get { return _isAutoSize; }
+ set { _isAutoSize = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="OHLCBar"/> properties to
+ /// default values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public OHLCBar() : this( LineBase.Default.Color )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets the
+ /// <see cref="Color"/> as specified, and the remaining
+ /// <see cref="OHLCBar"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="color">A <see cref="Color"/> value indicating
+ /// the color of the symbol
+ /// </param>
+ public OHLCBar( Color color ) : base( color )
+ {
+ _size = Default.Size;
+ _isAutoSize = Default.IsAutoSize;
+ _isOpenCloseVisible = Default.IsOpenCloseVisible;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="OHLCBar"/> object from which to copy</param>
+ public OHLCBar( OHLCBar rhs ) : base( rhs )
+ {
+ _isOpenCloseVisible = rhs._isOpenCloseVisible;
+ _size = rhs._size;
+ _isAutoSize = rhs._isAutoSize;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public OHLCBar Clone()
+ {
+ return new OHLCBar( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected OHLCBar( SerializationInfo info, StreamingContext context ) :
+ base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _isOpenCloseVisible = info.GetBoolean( "isOpenCloseVisible" );
+ _size = info.GetSingle( "size" );
+ _isAutoSize = info.GetBoolean( "isAutoSize" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema", schema );
+ info.AddValue( "isOpenCloseVisible", _isOpenCloseVisible );
+ info.AddValue( "size", _size );
+ info.AddValue( "isAutoSize", _isAutoSize );
+ }
+
+ #endregion
+
+ #region Rendering Methods
+
+
+ /// <summary>
+ /// Draw the <see cref="OHLCBar"/> to the specified <see cref="Graphics"/>
+ /// device at the specified location.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="isXBase">boolean value that indicates if the "base" axis for this
+ /// <see cref="OHLCBar"/> is the X axis. True for an <see cref="XAxis"/> base,
+ /// false for a <see cref="YAxis"/> or <see cref="Y2Axis"/> base.</param>
+ /// <param name="pixBase">The independent axis position of the center of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixHigh">The dependent axis position of the top of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixLow">The dependent axis position of the bottom of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixOpen">The dependent axis position of the opening value of the candlestick in
+ /// pixel units</param>
+ /// <param name="pixClose">The dependent axis position of the closing value of the candlestick in
+ /// pixel units</param>
+ /// <param name="halfSize">
+ /// The scaled width of the candlesticks, pixels</param>
+ /// <param name="pen">A pen with attributes of <see cref="Color"/> and
+ /// <see cref="LineBase.Width"/> for this <see cref="OHLCBar"/></param>
+ public void Draw( Graphics g, GraphPane pane, bool isXBase,
+ float pixBase, float pixHigh, float pixLow,
+ float pixOpen, float pixClose,
+ float halfSize, Pen pen )
+ {
+ if ( pixBase != PointPair.Missing )
+ {
+ if ( isXBase )
+ {
+ if ( Math.Abs( pixLow ) < 1000000 && Math.Abs( pixHigh ) < 1000000 )
+ g.DrawLine( pen, pixBase, pixHigh, pixBase, pixLow );
+ if ( _isOpenCloseVisible && Math.Abs( pixOpen ) < 1000000 )
+ g.DrawLine( pen, pixBase - halfSize, pixOpen, pixBase, pixOpen );
+ if ( _isOpenCloseVisible && Math.Abs( pixClose ) < 1000000 )
+ g.DrawLine( pen, pixBase, pixClose, pixBase + halfSize, pixClose );
+ }
+ else
+ {
+ if ( Math.Abs( pixLow ) < 1000000 && Math.Abs( pixHigh ) < 1000000 )
+ g.DrawLine( pen, pixHigh, pixBase, pixLow, pixBase );
+ if ( _isOpenCloseVisible && Math.Abs( pixOpen ) < 1000000 )
+ g.DrawLine( pen, pixOpen, pixBase - halfSize, pixOpen, pixBase );
+ if ( _isOpenCloseVisible && Math.Abs( pixClose ) < 1000000 )
+ g.DrawLine( pen, pixClose, pixBase, pixClose, pixBase + halfSize );
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Draw all the <see cref="OHLCBar"/>'s to the specified <see cref="Graphics"/>
+ /// device as a candlestick at each defined point.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="OHLCBarItem"/> object representing the
+ /// <see cref="OHLCBar"/>'s to be drawn.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
+ /// axis for the <see cref="OHLCBar"/></param>
+ /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
+ /// axis for the <see cref="OHLCBar"/></param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, OHLCBarItem curve,
+ Axis baseAxis, Axis valueAxis, float scaleFactor )
+ {
+ //ValueHandler valueHandler = new ValueHandler( pane, false );
+
+ float pixBase, pixHigh, pixLow, pixOpen, pixClose;
+
+ if ( curve.Points != null )
+ {
+ //float halfSize = _size * scaleFactor;
+ float halfSize = GetBarWidth( pane, baseAxis, scaleFactor );
+
+ using ( Pen pen = !curve.IsSelected ? new Pen( _color, _width ) :
+ new Pen( Selection.Border.Color, Selection.Border.Width ) )
+// using ( Pen pen = new Pen( _color, _penWidth ) )
+ {
+ // Loop over each defined point
+ for ( int i = 0; i < curve.Points.Count; i++ )
+ {
+ PointPair pt = curve.Points[i];
+ double date = pt.X;
+ double high = pt.Y;
+ double low = pt.Z;
+ double open = PointPair.Missing;
+ double close = PointPair.Missing;
+ if ( pt is StockPt )
+ {
+ open = ( pt as StockPt ).Open;
+ close = ( pt as StockPt ).Close;
+ }
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( !curve.Points[i].IsInvalid3D &&
+ ( date > 0 || !baseAxis._scale.IsLog ) &&
+ ( ( high > 0 && low > 0 ) || !valueAxis._scale.IsLog ) )
+ {
+ pixBase = (int)( baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, date ) + 0.5 );
+ //pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, date );
+ pixHigh = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, high );
+ pixLow = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, low );
+ if ( PointPair.IsValueInvalid( open ) )
+ pixOpen = Single.MaxValue;
+ else
+ pixOpen = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, open );
+
+ if ( PointPair.IsValueInvalid( close ) )
+ pixClose = Single.MaxValue;
+ else
+ pixClose = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, close );
+
+ if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
+ {
+ using ( Pen tPen = GetPen( pane, scaleFactor, pt ) )
+ Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis,
+ pixBase, pixHigh, pixLow, pixOpen,
+ pixClose, halfSize, tPen );
+ }
+ else
+ Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis,
+ pixBase, pixHigh, pixLow, pixOpen,
+ pixClose, halfSize, pen );
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the width of the candleStick, in pixels, based on the settings for
+ /// <see cref="Size"/> and <see cref="IsAutoSize"/>.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane"/> object.</param>
+ /// <param name="baseAxis">The <see cref="Axis"/> object that
+ /// represents the bar base (independent axis).</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>The width of each bar, in pixel units</returns>
+ public float GetBarWidth( GraphPane pane, Axis baseAxis, float scaleFactor )
+ {
+ float width;
+ if ( _isAutoSize )
+ width = baseAxis._scale.GetClusterWidth( _userScaleSize ) /
+ ( 1.0F + pane._barSettings.MinClusterGap ) / 2.0f;
+ else
+ width = (float)( _size * scaleFactor ) / 2.0f;
+
+ // use integral size
+ return (int)(width + 0.5f);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/OHLCBarItem.cs b/ZedGraph/OHLCBarItem.cs
new file mode 100644
index 0000000..10ff411
--- /dev/null
+++ b/ZedGraph/OHLCBarItem.cs
@@ -0,0 +1,344 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates a CandleStick curve type that displays a vertical (or horizontal)
+ /// line displaying the range of data values at each sample point, plus an starting
+ /// mark and an ending mark signifying the opening and closing value for the sample.
+ /// </summary>
+ /// <remarks>For this type to work properly, your <see cref="IPointList" /> must contain
+ /// <see cref="StockPt" /> objects, rather than ordinary <see cref="PointPair" /> types.
+ /// This is because the <see cref="OHLCBarItem"/> type actually displays 5 data values
+ /// but the <see cref="PointPair" /> only stores 3 data values. The <see cref="StockPt" />
+ /// stores <see cref="StockPt.Date" />, <see cref="StockPt.Close" />,
+ /// <see cref="StockPt.Open" />, <see cref="StockPt.High" />, and
+ /// <see cref="StockPt.Low" /> members.
+ /// For a vertical CandleStick chart, the opening value is drawn as a horizontal line
+ /// segment to the left of the vertical range bar, and the closing value is a horizontal
+ /// line segment to the right. The total length of these two line segments is controlled
+ /// by the <see cref="ZedGraph.OHLCBar.Size" /> property, which is specified in
+ /// points (1/72nd inch), and scaled according to <see cref="PaneBase.CalcScaleFactor" />.
+ /// The candlesticks are drawn horizontally or vertically depending on the
+ /// value of <see cref="BarSettings.Base"/>, which is a
+ /// <see cref="ZedGraph.BarBase"/> enum type.</remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-12-31 00:23:05 $ </version>
+ [Serializable]
+ public class OHLCBarItem : CurveItem, ICloneable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Private field that stores a reference to the <see cref="ZedGraph.OHLCBar"/>
+ /// class defined for this <see cref="OHLCBarItem"/>. Use the public
+ /// property <see cref="OHLCBar"/> to access this value.
+ /// </summary>
+ ///
+ protected OHLCBar _bar;
+
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets a reference to the <see cref="OHLCBar"/> class defined
+ /// for this <see cref="OHLCBarItem"/>.
+ /// </summary>
+ public OHLCBar Bar
+ {
+ get { return _bar; }
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return pane._barSettings.Base == BarBase.X;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <remarks>
+ /// IsZIncluded is true for <see cref="OHLCBarItem" /> objects, since the Y and Z
+ /// values are defined as the High and Low values for the day.</remarks>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return true;
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="OHLCBarItem"/>, specifying only the legend label.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ public OHLCBarItem( string label )
+ : base( label )
+ {
+ _bar = new OHLCBar();
+ }
+
+ /// <summary>
+ /// Create a new <see cref="OHLCBarItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The _label that will appear in the legend.</param>
+ /// <param name="points">An <see cref="IPointList"/> of double precision values that define
+ /// the Date, Close, Open, High, and Low values for the curve. Note that this
+ /// <see cref="IPointList" /> should contain <see cref="StockPt" /> items rather
+ /// than <see cref="PointPair" /> items.
+ /// </param>
+ /// <param name="color">
+ /// The <see cref="System.Drawing.Color" /> to use for drawing the candlesticks.</param>
+ public OHLCBarItem( string label, IPointList points, Color color )
+ : base( label, points )
+ {
+ _bar = new OHLCBar( color );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="OHLCBarItem"/> object from which to copy</param>
+ public OHLCBarItem( OHLCBarItem rhs )
+ : base( rhs )
+ {
+ _bar = rhs._bar.Clone();
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public OHLCBarItem Clone()
+ {
+ return new OHLCBarItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected OHLCBarItem( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _bar = (OHLCBar)info.GetValue( "stick", typeof( OHLCBar ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "stick", _bar );
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="OHLCBarItem"/> to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">The ordinal position of the current <see cref="OHLCBarItem"/>
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( _isVisible )
+ {
+ _bar.Draw( g, pane, this, this.BaseAxis( pane ),
+ this.ValueAxis( pane ), scaleFactor );
+ }
+ }
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="OHLCBarItem"/> at the specified location
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect,
+ float scaleFactor )
+ {
+ float pixBase, pixHigh, pixLow, pixOpen, pixClose;
+
+ if ( pane._barSettings.Base == BarBase.X )
+ {
+ pixBase = rect.Left + rect.Width / 2.0F;
+ pixHigh = rect.Top;
+ pixLow = rect.Bottom;
+ pixOpen = pixHigh + rect.Height / 4;
+ pixClose = pixLow - rect.Height / 4;
+ }
+ else
+ {
+ pixBase = rect.Top + rect.Height / 2.0F;
+ pixHigh = rect.Right;
+ pixLow = rect.Left;
+ pixOpen = pixHigh - rect.Width / 4;
+ pixClose = pixLow + rect.Width / 4;
+ }
+
+ float halfSize = 2.0f * scaleFactor;
+
+ using ( Pen pen = new Pen( _bar.Color, _bar._width ) )
+ {
+ _bar.Draw( g, pane, pane._barSettings.Base == BarBase.X, pixBase, pixHigh,
+ pixLow, pixOpen, pixClose, halfSize, pen );
+ }
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ override public bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = string.Empty;
+
+ if ( i < 0 || i >= _points.Count )
+ return false;
+
+ Axis valueAxis = ValueAxis( pane );
+ Axis baseAxis = BaseAxis( pane );
+
+ float halfSize = _bar.Size * pane.CalcScaleFactor();
+
+ PointPair pt = _points[i];
+ double date = pt.X;
+ double high = pt.Y;
+ double low = pt.Z;
+
+ if ( !pt.IsInvalid3D &&
+ ( date > 0 || !baseAxis._scale.IsLog ) &&
+ ( ( high > 0 && low > 0 ) || !valueAxis._scale.IsLog ) )
+ {
+ float pixBase, pixHigh, pixLow;
+ pixBase = baseAxis.Scale.Transform( _isOverrideOrdinal, i, date );
+ pixHigh = valueAxis.Scale.Transform( _isOverrideOrdinal, i, high );
+ pixLow = valueAxis.Scale.Transform( _isOverrideOrdinal, i, low );
+
+ // Calculate the pixel location for the side of the bar (on the base axis)
+ float pixSide = pixBase - halfSize;
+
+ // Draw the bar
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixSide, pixLow,
+ pixSide + halfSize * 2, pixHigh );
+ else
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}",
+ pixLow, pixSide,
+ pixHigh, pixSide + halfSize * 2 );
+
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/OrdinalScale.cs b/ZedGraph/OrdinalScale.cs
new file mode 100644
index 0000000..92f9e0b
--- /dev/null
+++ b/ZedGraph/OrdinalScale.cs
@@ -0,0 +1,232 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The OrdinalScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.Ordinal" />.
+ /// </summary>
+ /// <remarks>
+ /// OrdinalScale is an ordinal axis with tic labels generated at integral values. An ordinal axis means that
+ /// all data points are evenly spaced at integral values, and the actual coordinate values
+ /// for points corresponding to that axis are ignored. That is, if the X axis is an
+ /// ordinal type, then all X values associated with the curves are ignored.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.8 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ class OrdinalScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ /// <summary>
+ /// Default constructor that defines the owner <see cref="Axis" />
+ /// (containing object) for this new object.
+ /// </summary>
+ /// <param name="owner">The owner, or containing object, of this instance</param>
+ public OrdinalScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="OrdinalScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="OrdinalScale" /></param>
+ public OrdinalScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new OrdinalScale( this, owner );
+ }
+
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Return the <see cref="AxisType" /> for this <see cref="Scale" />, which is
+ /// <see cref="AxisType.Ordinal" />.
+ /// </summary>
+ public override AxisType Type
+ {
+ get { return AxisType.Ordinal; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Select a reasonable ordinal axis scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.Ordinal"/> type axes, and it
+ /// is called by the general <see cref="Scale.PickScale"/> method. The scale range is chosen
+ /// based on increments of 1, 2, or 5 (because they are even divisors of 10).
+ /// Being an ordinal axis type, the <see cref="Scale.MajorStep" /> value will always be integral. This
+ /// method honors the <see cref="Scale.MinAuto" />, <see cref="Scale.MaxAuto" />,
+ /// and <see cref="Scale.MajorStepAuto" /> autorange settings.
+ /// In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Scale.Min" />, <see cref="Scale.Max" />, or <see cref="Scale.MajorStep" />
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values. The basic defaults for
+ /// scale selection are defined using <see cref="Scale.Default.ZeroLever" />,
+ /// <see cref="Scale.Default.TargetXSteps" />, and <see cref="Scale.Default.TargetYSteps" />
+ /// from the <see cref="Scale.Default" /> default class.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="AxisType.Ordinal"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ PickScale( pane, g, scaleFactor, this );
+ }
+
+ internal static void PickScale( GraphPane pane, Graphics g, float scaleFactor, Scale scale )
+ {
+ // Test for trivial condition of range = 0 and pick a suitable default
+ if ( scale._max - scale._min < 1.0 )
+ {
+ if ( scale._maxAuto )
+ scale._max = scale._min + 0.5;
+ else
+ scale._min = scale._max - 0.5;
+ }
+ else
+ {
+ // Calculate the new step size
+ if ( scale._majorStepAuto )
+ {
+ // Calculate the step size based on targetSteps
+ scale._majorStep = Scale.CalcStepSize( scale._max - scale._min,
+ ( scale._ownerAxis is XAxis || scale._ownerAxis is X2Axis ) ?
+ Default.TargetXSteps : Default.TargetYSteps );
+
+ if ( scale.IsPreventLabelOverlap )
+ {
+ // Calculate the maximum number of labels
+ double maxLabels = (double) scale.CalcMaxLabels( g, pane, scaleFactor );
+
+ // Calculate a step size based on the width of the labels
+ double tmpStep = Math.Ceiling( ( scale._max - scale._min ) / maxLabels );
+
+ // Use the greater of the two step sizes
+ if ( tmpStep > scale._majorStep )
+ scale._majorStep = tmpStep;
+ }
+
+ }
+
+ scale._majorStep = (int)scale._majorStep;
+ if ( scale._majorStep < 1.0 )
+ scale._majorStep = 1.0;
+
+ // Calculate the new minor step size
+ if ( scale._minorStepAuto )
+ scale._minorStep = Scale.CalcStepSize( scale._majorStep,
+ ( scale._ownerAxis is XAxis || scale._ownerAxis is X2Axis ) ?
+ Default.TargetMinorXSteps : Default.TargetMinorYSteps );
+
+ if ( scale._minAuto )
+ scale._min -= 0.5;
+ if ( scale._maxAuto )
+ scale._max += 0.5;
+ }
+ }
+
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected OrdinalScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PaneBase.cs b/ZedGraph/PaneBase.cs
new file mode 100644
index 0000000..b5bc6f0
--- /dev/null
+++ b/ZedGraph/PaneBase.cs
@@ -0,0 +1,1219 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Drawing.Imaging;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.IO;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An abstract base class that defines basic functionality for handling a pane. This class is the
+ /// parent class for <see cref="MasterPane"/> and <see cref="GraphPane"/>.
+ /// </summary>
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.32 $ $Date: 2007-11-05 18:28:56 $ </version>
+ abstract public class PaneBase : ICloneable
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// The rectangle that defines the full area into which the pane is rendered. Units are pixels.
+ /// Use the public property <see cref="Rect"/> to access this value.
+ /// </summary>
+ protected RectangleF _rect;
+
+ /// <summary>Private field that holds the main title of the pane. Use the
+ /// public property <see cref="Title"/> to access this value.
+ /// </summary>
+ protected GapLabel _title;
+
+ /// <summary>Private field instance of the <see cref="ZedGraph.Legend"/> class. Use the
+ /// public property <see cref="PaneBase.Legend"/> to access this class.</summary>
+ protected Legend _legend;
+
+ /// <summary>
+ /// Private field that stores the user-defined tag for this <see cref="PaneBase"/>. This tag
+ /// can be any user-defined value. If it is a <see cref="String"/> type, it can be used as
+ /// a parameter to the <see cref="PaneList.IndexOfTag"/> method. Use the public property
+ /// <see cref="Tag"/> to access this value.
+ /// </summary>
+ protected object _tag;
+
+ /// <summary>
+ /// private field to store the margin values for this <see cref="PaneBase" />. Use the
+ /// public property <see cref="Margin" /> to access this property.
+ /// </summary>
+ internal Margin _margin;
+
+ /// <summary>Private field that determines whether or not the fonts, tics, gaps, etc.
+ /// will be scaled according to the actual graph size. true for font and feature scaling
+ /// with graph size, false for fixed font sizes (scaleFactor = 1.0 constant).
+ /// Use the public property <see cref="IsFontsScaled"/> to access this value. </summary>
+ /// <seealso cref="CalcScaleFactor"/>
+ /// <seealso cref="IsPenWidthScaled"/>
+ protected bool _isFontsScaled;
+ /// <summary>
+ /// Private field that controls whether or not pen widths are scaled according to the
+ /// size of the graph. This value is only applicable if <see cref="IsFontsScaled"/>
+ /// is true. If <see cref="IsFontsScaled"/> is false, then no scaling will be done,
+ /// regardless of the value of <see cref="IsPenWidthScaled"/>.
+ /// </summary>
+ /// <value>true to scale the pen widths according to the size of the graph,
+ /// false otherwise.</value>
+ /// <seealso cref="IsFontsScaled"/>
+ /// <seealso cref="CalcScaleFactor"/>
+ protected bool _isPenWidthScaled;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for the
+ /// <see cref="Rect"/> background. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ protected Fill _fill;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Border"/> data for the
+ /// <see cref="Rect"/> border. Use the public property <see cref="Border"/> to
+ /// access this value.
+ /// </summary>
+ protected Border _border;
+
+ /// <summary>Private field instance of the <see cref="ZedGraph.GraphObjList"/> class. Use the
+ /// public property <see cref="GraphObjList"/> to access this class.</summary>
+ protected GraphObjList _graphObjList;
+
+ /// <summary>Private field that determines the base size of the pane, in inches.
+ /// Fonts, tics, gaps, etc. are scaled according to this base size.
+ /// Use the public property <see cref="BaseDimension"/> to access this value. </summary>
+ /// <seealso cref="_isFontsScaled"/>
+ /// <seealso cref="CalcScaleFactor"/>
+ protected float _baseDimension;
+
+ /// <summary>
+ /// private field that stores the gap between the bottom of the pane title and the
+ /// client area of the pane. This is expressed as a fraction of the title character height.
+ /// </summary>
+ protected float _titleGap;
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the default property values for the <see cref="PaneBase"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default GraphPane properties
+ /// <summary>
+ /// The default display mode for the title at the top of the pane
+ /// (<see cref="PaneBase.Title"/> <see cref="Label.IsVisible" /> property). true to
+ /// display a title, false otherwise.
+ /// </summary>
+ public static bool IsShowTitle = true;
+
+ /// <summary>
+ /// The default font family for the title
+ /// (<see cref="PaneBase.Title"/> property).
+ /// </summary>
+ public static string FontFamily = "Arial";
+ /// <summary>
+ /// The default font size (points) for the
+ /// <see cref="PaneBase.Title"/> (<see cref="ZedGraph.FontSpec.Size"/> property).
+ /// </summary>
+ public static float FontSize = 16;
+ /// <summary>
+ /// The default font color for the
+ /// <see cref="PaneBase.Title"/>
+ /// (<see cref="ZedGraph.FontSpec.FontColor"/> property).
+ /// </summary>
+ public static Color FontColor = Color.Black;
+ /// <summary>
+ /// The default font bold mode for the
+ /// <see cref="PaneBase.Title"/>
+ /// (<see cref="ZedGraph.FontSpec.IsBold"/> property). true
+ /// for a bold typeface, false otherwise.
+ /// </summary>
+ public static bool FontBold = true;
+ /// <summary>
+ /// The default font italic mode for the
+ /// <see cref="PaneBase.Title"/>
+ /// (<see cref="ZedGraph.FontSpec.IsItalic"/> property). true
+ /// for an italic typeface, false otherwise.
+ /// </summary>
+ public static bool FontItalic = false;
+ /// <summary>
+ /// The default font underline mode for the
+ /// <see cref="PaneBase.Title"/>
+ /// (<see cref="ZedGraph.FontSpec.IsUnderline"/> property). true
+ /// for an underlined typeface, false otherwise.
+ /// </summary>
+ public static bool FontUnderline = false;
+
+ /// <summary>
+ /// The default border mode for the <see cref="PaneBase"/>.
+ /// (<see cref="PaneBase.Border"/> property). true
+ /// to draw a border around the <see cref="PaneBase.Rect"/>,
+ /// false otherwise.
+ /// </summary>
+ public static bool IsBorderVisible = true;
+ /// <summary>
+ /// The default color for the <see cref="PaneBase"/> border.
+ /// (<see cref="PaneBase.Border"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default color for the <see cref="PaneBase.Rect"/> background.
+ /// (<see cref="PaneBase.Fill"/> property).
+ /// </summary>
+ public static Color FillColor = Color.White;
+
+ /// <summary>
+ /// The default pen width for the <see cref="PaneBase"/> border.
+ /// (<see cref="PaneBase.Border"/> property). Units are in points (1/72 inch).
+ /// </summary>
+ public static float BorderPenWidth = 1;
+
+ /// <summary>
+ /// The default dimension of the <see cref="PaneBase.Rect"/>, which
+ /// defines a normal sized plot. This dimension is used to scale the
+ /// fonts, symbols, etc. according to the actual size of the
+ /// <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <seealso cref="PaneBase.CalcScaleFactor"/>
+ public static float BaseDimension = 8.0F;
+
+ /// <summary>
+ /// The default setting for the <see cref="PaneBase.IsPenWidthScaled"/> option.
+ /// true to have all pen widths scaled according to <see cref="PaneBase.BaseDimension"/>,
+ /// false otherwise.
+ /// </summary>
+ /// <seealso cref="PaneBase.CalcScaleFactor"/>
+ public static bool IsPenWidthScaled = false;
+ /// <summary>
+ /// The default setting for the <see cref="PaneBase.IsFontsScaled"/> option.
+ /// true to have all fonts scaled according to <see cref="PaneBase.BaseDimension"/>,
+ /// false otherwise.
+ /// </summary>
+ /// <seealso cref="PaneBase.CalcScaleFactor"/>
+ public static bool IsFontsScaled = true;
+
+ /// <summary>
+ /// The default value for the <see cref="PaneBase.TitleGap" /> property, expressed as
+ /// a fraction of the scaled <see cref="Title" /> character height.
+ /// </summary>
+ public static float TitleGap = 0.5f;
+ }
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// The rectangle that defines the full area into which all graphics
+ /// will be rendered.
+ /// </summary>
+ /// <remarks>Note that this rectangle has x, y, width, and height. Most of the
+ /// GDI+ graphic primitive actually draw one pixel beyond those dimensions. For
+ /// example, for a rectangle of ( X=0, Y=0, Width=100, Height=100 ), GDI+ would
+ /// draw into pixels 0 through 100, which is actually 101 pixels. For the
+ /// ZedGraph Rect, a Width of 100 pixels means that pixels 0 through 99 are used</remarks>
+ /// <value>Units are pixels.</value>
+ /// <seealso cref="ReSize"/>
+ public RectangleF Rect
+ {
+ get { return _rect; }
+ set { _rect = value; }
+ }
+
+ /// <summary>
+ /// Accesses the <see cref="Legend"/> for this <see cref="PaneBase"/>
+ /// </summary>
+ /// <value>A reference to a <see cref="Legend"/> object</value>
+ public Legend Legend
+ {
+ get { return _legend; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Label" /> instance that contains the text and attributes of the title.
+ /// This text can be multiple lines separated by newline characters ('\n').
+ /// </summary>
+ /// <seealso cref="FontSpec"/>
+ /// <seealso cref="Default.FontColor"/>
+ /// <seealso cref="Default.FontBold"/>
+ /// <seealso cref="Default.FontItalic"/>
+ /// <seealso cref="Default.FontUnderline"/>
+ /// <seealso cref="Default.FontFamily"/>
+ /// <seealso cref="Default.FontSize"/>
+ public Label Title
+ {
+ get { return _title; }
+ }
+
+ /// <summary>
+ /// Gets or sets the user-defined tag for this <see cref="PaneBase"/>. This tag
+ /// can be any user-defined value. If it is a <see cref="String"/> type, it can be used as
+ /// a parameter to the <see cref="PaneList.IndexOfTag"/> method.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if you are going to Serialize ZedGraph data, then any type
+ /// that you store in <see cref="Tag"/> must be a serializable type (or
+ /// it will cause an exception).
+ /// </remarks>
+ public object Tag
+ {
+ get { return _tag; }
+ set { _tag = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Border"/> class for drawing the border
+ /// border around the <see cref="Rect"/>
+ /// </summary>
+ /// <seealso cref="Default.BorderColor"/>
+ /// <seealso cref="Default.BorderPenWidth"/>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for the
+ /// filling the background of the <see cref="Rect"/>.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the list of <see cref="GraphObj"/> items for this <see cref="GraphPane"/>
+ /// </summary>
+ /// <value>A reference to a <see cref="GraphObjList"/> collection object</value>
+ public GraphObjList GraphObjList
+ {
+ get { return _graphObjList; }
+ set { _graphObjList = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Margin" /> instance that controls the space between
+ /// the edge of the <see cref="PaneBase.Rect" /> and the rendered content of the graph.
+ /// </summary>
+ public Margin Margin
+ {
+ get { return _margin; }
+ set { _margin = value; }
+ }
+
+ /// <summary>
+ /// BaseDimension is a double precision value that sets "normal" pane size on
+ /// which all the settings are based. The BaseDimension is in inches. For
+ /// example, if the BaseDimension is 8.0 inches and the
+ /// <see cref="Title"/> size is 14 points. Then the pane title font
+ /// will be 14 points high when the <see cref="Rect"/> is approximately 8.0
+ /// inches wide. If the Rect is 4.0 inches wide, the pane title font will be
+ /// 7 points high. Most features of the graph are scaled in this manner.
+ /// </summary>
+ /// <value>The base dimension reference for the <see cref="Rect"/>, in inches</value>
+ /// <seealso cref="Default.BaseDimension"/>
+ /// <seealso cref="IsFontsScaled"/>
+ /// <seealso cref="CalcScaleFactor"/>
+ public float BaseDimension
+ {
+ get { return _baseDimension; }
+ set { _baseDimension = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the gap between the bottom of the pane title and the
+ /// client area of the pane. This is expressed as a fraction of the scaled
+ /// <see cref="Title" /> character height.
+ /// </summary>
+ public float TitleGap
+ {
+ get { return _titleGap; }
+ set { _titleGap = value; }
+ }
+
+ /// <summary>
+ /// Determines if the font sizes, tic sizes, gap sizes, etc. will be scaled according to
+ /// the size of the <see cref="Rect"/> and the <see cref="BaseDimension"/>. If this
+ /// value is set to false, then the font sizes and tic sizes will always be exactly as
+ /// specified, without any scaling.
+ /// </summary>
+ /// <value>True to have the fonts and tics scaled, false to have them constant</value>
+ /// <seealso cref="PaneBase.CalcScaleFactor"/>
+ public bool IsFontsScaled
+ {
+ get { return _isFontsScaled; }
+ set { _isFontsScaled = value; }
+ }
+ /// <summary>
+ /// Gets or sets the property that controls whether or not pen widths are scaled for this
+ /// <see cref="PaneBase"/>.
+ /// </summary>
+ /// <remarks>This value is only applicable if <see cref="IsFontsScaled"/>
+ /// is true. If <see cref="IsFontsScaled"/> is false, then no scaling will be done,
+ /// regardless of the value of <see cref="IsPenWidthScaled"/>. Note that scaling the pen
+ /// widths can cause "artifacts" to appear at typical screen resolutions. This occurs
+ /// because of roundoff differences; in some cases the pen width may round to 1 pixel wide
+ /// and in another it may round to 2 pixels wide. The result is typically undesirable.
+ /// Therefore, this option defaults to false. This option is primarily useful for high
+ /// resolution output, such as printer output or high resolution bitmaps (from
+ /// <see cref="GetImage(int,int,float)"/>) where it is desirable to have the pen width
+ /// be consistent with the screen image.
+ /// </remarks>
+ /// <value>true to scale the pen widths according to the size of the graph,
+ /// false otherwise.</value>
+ /// <seealso cref="IsFontsScaled"/>
+ /// <seealso cref="CalcScaleFactor"/>
+ public bool IsPenWidthScaled
+ {
+ get { return _isPenWidthScaled; }
+ set { _isPenWidthScaled = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the <see cref="PaneBase"/> class. Leaves the <see cref="Rect"/> empty.
+ /// </summary>
+ public PaneBase() : this( "", new RectangleF( 0, 0, 0, 0 ) )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor for the <see cref="PaneBase"/> class. Specifies the <see cref="Title"/> of
+ /// the <see cref="PaneBase"/>, and the size of the <see cref="Rect"/>.
+ /// </summary>
+ public PaneBase( string title, RectangleF paneRect )
+ {
+ _rect = paneRect;
+
+ _legend = new Legend();
+
+ _baseDimension = Default.BaseDimension;
+ _margin = new Margin();
+ _titleGap = Default.TitleGap;
+
+ _isFontsScaled = Default.IsFontsScaled;
+ _isPenWidthScaled = Default.IsPenWidthScaled;
+ _fill = new Fill( Default.FillColor );
+ _border = new Border( Default.IsBorderVisible, Default.BorderColor,
+ Default.BorderPenWidth );
+
+ _title = new GapLabel( title, Default.FontFamily,
+ Default.FontSize, Default.FontColor, Default.FontBold,
+ Default.FontItalic, Default.FontUnderline );
+ _title._fontSpec.Fill.IsVisible = false;
+ _title._fontSpec.Border.IsVisible = false;
+
+ _graphObjList = new GraphObjList();
+
+ _tag = null;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="PaneBase"/> object from which to copy</param>
+ public PaneBase( PaneBase rhs )
+ {
+ // copy over all the value types
+ _isFontsScaled = rhs._isFontsScaled;
+ _isPenWidthScaled = rhs._isPenWidthScaled;
+
+ _titleGap = rhs._titleGap;
+ _baseDimension = rhs._baseDimension;
+ _margin = rhs._margin.Clone();
+ _rect = rhs._rect;
+
+ // Copy the reference types by cloning
+ _fill = rhs._fill.Clone();
+ _border = rhs._border.Clone();
+ _title = rhs._title.Clone();
+
+ _legend = rhs.Legend.Clone();
+ _title = rhs._title.Clone();
+ _graphObjList = rhs._graphObjList.Clone();
+
+ if ( rhs._tag is ICloneable )
+ _tag = ((ICloneable) rhs._tag).Clone();
+ else
+ _tag = rhs._tag;
+ }
+
+
+ //abstract public object ShallowClone();
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of Clone
+ /// </summary>
+ /// <remarks>
+ /// Note that this method must be called with an explicit cast to ICloneable, and
+ /// that it is inherently virtual. For example:
+ /// <code>
+ /// ParentClass foo = new ChildClass();
+ /// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
+ /// </code>
+ /// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
+ /// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
+ /// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
+ /// </remarks>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
+ //return new PaneBase( this );
+ }
+
+ /// <summary>
+ /// Create a shallow, memberwise copy of this class.
+ /// </summary>
+ /// <remarks>
+ /// Note that this method uses MemberWiseClone, which will copy all
+ /// members (shallow) including those of classes derived from this class.</remarks>
+ /// <returns>a new copy of the class</returns>
+ public PaneBase ShallowClone()
+ {
+ // return a shallow copy
+ return this.MemberwiseClone() as PaneBase;
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ // schema changed to 2 when Label Class added
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PaneBase( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _rect = (RectangleF) info.GetValue( "rect", typeof(RectangleF) );
+ _legend = (Legend) info.GetValue( "legend", typeof(Legend) );
+ _title = (GapLabel) info.GetValue( "title", typeof(GapLabel) );
+ //this.isShowTitle = info.GetBoolean( "isShowTitle" );
+ _isFontsScaled = info.GetBoolean( "isFontsScaled" );
+ _isPenWidthScaled = info.GetBoolean( "isPenWidthScaled" );
+ //this.fontSpec = (FontSpec) info.GetValue( "fontSpec" , typeof(FontSpec) );
+ _titleGap = info.GetSingle( "titleGap" );
+ _fill = (Fill) info.GetValue( "fill", typeof(Fill) );
+ _border = (Border) info.GetValue( "border", typeof(Border) );
+ _baseDimension = info.GetSingle( "baseDimension" );
+ _margin = (Margin)info.GetValue( "margin", typeof( Margin ) );
+ _graphObjList = (GraphObjList) info.GetValue( "graphObjList", typeof(GraphObjList) );
+
+ _tag = info.GetValue( "tag", typeof(object) );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "rect", _rect );
+ info.AddValue( "legend", _legend );
+ info.AddValue( "title", _title );
+ //info.AddValue( "isShowTitle", isShowTitle );
+ info.AddValue( "isFontsScaled", _isFontsScaled );
+ info.AddValue( "isPenWidthScaled", _isPenWidthScaled );
+ info.AddValue( "titleGap", _titleGap );
+
+ //info.AddValue( "fontSpec", fontSpec );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "baseDimension", _baseDimension );
+ info.AddValue( "margin", _margin );
+ info.AddValue( "graphObjList", _graphObjList );
+
+ info.AddValue( "tag", _tag );
+ }
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Do all rendering associated with this <see cref="PaneBase"/> to the specified
+ /// <see cref="Graphics"/> device. This abstract method is implemented by the child
+ /// classes.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ public virtual void Draw( Graphics g )
+ {
+ if ( _rect.Width <= 1 || _rect.Height <= 1 )
+ return;
+
+ // calculate scaleFactor on "normal" pane size (BaseDimension)
+ float scaleFactor = this.CalcScaleFactor();
+
+ // Fill the pane background and draw a border around it
+ DrawPaneFrame( g, scaleFactor );
+
+ // Clip everything to the rect
+ g.SetClip( _rect );
+
+ // Draw the GraphItems that are behind everything
+ _graphObjList.Draw( g, this, scaleFactor, ZOrder.H_BehindAll );
+
+ // Draw the Pane Title
+ DrawTitle( g, scaleFactor );
+
+ // Draw the Legend
+ //this.Legend.Draw( g, this, scaleFactor );
+
+ // Reset the clipping
+ g.ResetClip();
+ }
+
+ /// <summary>
+ /// Calculate the client area rectangle based on the <see cref="PaneBase.Rect"/>.
+ /// </summary>
+ /// <remarks>The client rectangle is the actual area available for <see cref="GraphPane"/>
+ /// or <see cref="MasterPane"/> items after taking out space for the margins and the title.
+ /// This method does not take out the area required for the <see cref="PaneBase.Legend"/>.
+ /// To do so, you must separately call <see cref="ZedGraph.Legend.CalcRect"/>.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.Default.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <returns>The calculated chart rect, in pixel coordinates.</returns>
+ public RectangleF CalcClientRect( Graphics g, float scaleFactor )
+ {
+ // get scaled values for the paneGap and character height
+ //float scaledOuterGap = (float) ( Default.OuterPaneGap * scaleFactor );
+ float charHeight = _title._fontSpec.GetHeight( scaleFactor );
+
+ // chart rect starts out at the full pane rect. It gets reduced to make room for the legend,
+ // scales, titles, etc.
+ RectangleF innerRect = new RectangleF(
+ _rect.Left + _margin.Left * scaleFactor,
+ _rect.Top + _margin.Top * scaleFactor,
+ _rect.Width - scaleFactor * ( _margin.Left + _margin.Right ),
+ _rect.Height - scaleFactor * ( _margin.Top + _margin.Bottom ) );
+
+ // Leave room for the title
+ if ( _title._isVisible && _title._text != string.Empty )
+ {
+ SizeF titleSize = _title._fontSpec.BoundingBox( g, _title._text, scaleFactor );
+ // Leave room for the title height, plus a line spacing of charHeight * _titleGap
+ innerRect.Y += titleSize.Height + charHeight * _titleGap;
+ innerRect.Height -= titleSize.Height + charHeight * _titleGap;
+ }
+
+ // Calculate the legend rect, and back it out of the current ChartRect
+ //this.legend.CalcRect( g, this, scaleFactor, ref innerRect );
+
+ return innerRect;
+ }
+
+ /// <summary>
+ /// Draw the border _border around the <see cref="Rect"/> area.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ public void DrawPaneFrame( Graphics g, float scaleFactor )
+ {
+ // Erase the pane background, filling it with the specified brush
+ _fill.Draw( g, _rect );
+
+ // Reduce the rect width and height by 1 pixel so that for a rect of
+ // new RectangleF( 0, 0, 100, 100 ), which should be 100 pixels wide, we cover
+ // from 0 through 99. The draw routines normally cover from 0 through 100, which is
+ // actually 101 pixels wide.
+ RectangleF rect = new RectangleF( _rect.X, _rect.Y, _rect.Width - 1, _rect.Height - 1 );
+
+ _border.Draw( g, this, scaleFactor, rect );
+ }
+
+ /// <summary>
+ /// Draw the <see cref="Title"/> on the graph, centered at the top of the pane.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ public void DrawTitle( Graphics g, float scaleFactor )
+ {
+ // only draw the title if it's required
+ if ( _title._isVisible )
+ {
+ SizeF size = _title._fontSpec.BoundingBox( g, _title._text, scaleFactor );
+
+ // use the internal fontSpec class to draw the text using user-specified and/or
+ // default attributes.
+ _title._fontSpec.Draw( g, this, _title._text,
+ ( _rect.Left + _rect.Right ) / 2,
+ _rect.Top + _margin.Top * (float) scaleFactor + size.Height / 2.0F,
+ AlignH.Center, AlignV.Center, scaleFactor );
+ }
+ }
+
+ /// <summary>
+ /// Change the size of the <see cref="Rect"/>. Override this method to handle resizing the contents
+ /// as required.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">The new size for the <see cref="Rect"/>.</param>
+ public virtual void ReSize( Graphics g, RectangleF rect )
+ {
+ _rect = rect;
+ }
+
+ /// <summary>
+ /// Calculate the scaling factor based on the ratio of the current <see cref="Rect"/> dimensions and
+ /// the <see cref="Default.BaseDimension"/>.
+ /// </summary>
+ /// <remarks>This scaling factor is used to proportionally scale the
+ /// features of the <see cref="MasterPane"/> so that small graphs don't have huge fonts, and vice versa.
+ /// The scale factor represents a linear multiple to be applied to font sizes, symbol sizes, tic sizes,
+ /// gap sizes, pen widths, etc. The units of the scale factor are "World Pixels" per "Standard Point".
+ /// If any object size, in points, is multiplied by this scale factor, the result is the size, in pixels,
+ /// that the object should be drawn using the standard GDI+ drawing instructions. A "Standard Point"
+ /// is a dimension based on points (1/72nd inch) assuming that the <see cref="Rect"/> size
+ /// matches the <see cref="Default.BaseDimension"/>.
+ /// Note that "World Pixels" will still be transformed by the GDI+ transform matrices to result
+ /// in "Output Device Pixels", but "World Pixels" are the reference basis for the drawing commands.
+ /// </remarks>
+ /// <returns>
+ /// A <see cref="Single"/> value representing the scaling factor to use for the rendering calculations.
+ /// </returns>
+ /// <seealso cref="PaneBase.BaseDimension"/>
+ public float CalcScaleFactor()
+ {
+ float scaleFactor; //, xInch, yInch;
+ const float ASPECTLIMIT = 1.5F;
+
+ // if font scaling is turned off, then always return a 1.0 scale factor
+ if ( !_isFontsScaled )
+ return 1.0f;
+
+ // Assume the standard width (BaseDimension) is 8.0 inches
+ // Therefore, if the rect is 8.0 inches wide, then the fonts will be scaled at 1.0
+ // if the rect is 4.0 inches wide, the fonts will be half-sized.
+ // if the rect is 16.0 inches wide, the fonts will be double-sized.
+
+ // Scale the size depending on the client area width in linear fashion
+ if ( _rect.Height <= 0 )
+ return 1.0F;
+ float length = _rect.Width;
+ float aspect = _rect.Width / _rect.Height;
+ if ( aspect > ASPECTLIMIT )
+ length = _rect.Height * ASPECTLIMIT;
+ if ( aspect < 1.0F / ASPECTLIMIT )
+ length = _rect.Width * ASPECTLIMIT;
+
+ scaleFactor = length / ( _baseDimension * 72F );
+
+ // Don't let the scaleFactor get ridiculous
+ if ( scaleFactor < 0.1F )
+ scaleFactor = 0.1F;
+
+ return scaleFactor;
+ }
+
+ /// <summary>
+ /// Calculate the scaled pen width, taking into account the scaleFactor and the
+ /// setting of the <see cref="IsPenWidthScaled"/> property of the pane.
+ /// </summary>
+ /// <param name="penWidth">The pen width, in points (1/72 inch)</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <returns>The scaled pen width, in world pixels</returns>
+ public float ScaledPenWidth( float penWidth, float scaleFactor )
+ {
+ if ( _isPenWidthScaled )
+ return (float)( penWidth * scaleFactor );
+ else
+ return penWidth;
+ }
+
+ /// <summary>
+ /// Build a <see cref="Bitmap"/> object containing the graphical rendering of
+ /// all the <see cref="GraphPane"/> objects in this list.
+ /// </summary>
+ /// <value>A <see cref="Bitmap"/> object rendered with the current graph.</value>
+ /// <seealso cref="GetImage(int,int,float)"/>
+ /// <seealso cref="GetMetafile()"/>
+ /// <seealso cref="GetMetafile(int,int)"/>
+ public Bitmap GetImage()
+ {
+ return GetImage( false );
+ }
+
+ /// <summary>
+ /// Build a <see cref="Bitmap"/> object containing the graphical rendering of
+ /// all the <see cref="GraphPane"/> objects in this list.
+ /// </summary>
+ /// <value>A <see cref="Bitmap"/> object rendered with the current graph.</value>
+ /// <seealso cref="GetImage(int,int,float)"/>
+ /// <seealso cref="GetMetafile()"/>
+ /// <seealso cref="GetMetafile(int,int)"/>
+ public Bitmap GetImage( bool isAntiAlias )
+ {
+ Bitmap bitmap = new Bitmap( (int) _rect.Width, (int) _rect.Height );
+ using ( Graphics bitmapGraphics = Graphics.FromImage( bitmap ) )
+ {
+ bitmapGraphics.TranslateTransform( -_rect.Left, -_rect.Top );
+ this.Draw( bitmapGraphics );
+ }
+
+ return bitmap;
+ }
+
+ /// <summary>
+ /// Gets an image for the current GraphPane, scaled to the specified size and resolution.
+ /// </summary>
+ /// <param name="width">The scaled width of the bitmap in pixels</param>
+ /// <param name="height">The scaled height of the bitmap in pixels</param>
+ /// <param name="dpi">The resolution of the bitmap, in dots per inch</param>
+ /// <param name="isAntiAlias">true for anti-aliased rendering, false otherwise</param>
+ /// <seealso cref="GetImage()"/>
+ /// <seealso cref="GetMetafile()"/>
+ /// <seealso cref="GetMetafile(int,int)"/>
+ /// <seealso cref="Bitmap"/>
+ public Bitmap GetImage( int width, int height, float dpi, bool isAntiAlias )
+ {
+ Bitmap bitmap = new Bitmap( width, height );
+ bitmap.SetResolution( dpi, dpi );
+ using ( Graphics bitmapGraphics = Graphics.FromImage( bitmap ) )
+ {
+ MakeImage( bitmapGraphics, width, height, isAntiAlias );
+ }
+
+ return bitmap;
+ }
+
+ /// <summary>
+ /// Gets an image for the current GraphPane, scaled to the specified size and resolution.
+ /// </summary>
+ /// <param name="width">The scaled width of the bitmap in pixels</param>
+ /// <param name="height">The scaled height of the bitmap in pixels</param>
+ /// <param name="dpi">The resolution of the bitmap, in dots per inch</param>
+ /// <seealso cref="GetImage()"/>
+ /// <seealso cref="GetMetafile()"/>
+ /// <seealso cref="GetMetafile(int,int)"/>
+ /// <seealso cref="Bitmap"/>
+ public Bitmap GetImage( int width, int height, float dpi )
+ {
+ return GetImage( width, height, dpi, false );
+ }
+
+ /// <summary>
+ /// Setup a <see cref="Graphics" /> instance with appropriate antialias settings.
+ /// </summary>
+ /// <remarks>
+ /// No settings are modified if <paramref name="isAntiAlias"/> is set to false. This method
+ /// does not restore original settings, it presumes that the Graphics instance will be
+ /// disposed.</remarks>
+ /// <param name="g">An existing <see cref="Graphics" /> instance</param>
+ /// <param name="isAntiAlias">true to render in anti-alias mode, false otherwise</param>
+ internal void SetAntiAliasMode( Graphics g, bool isAntiAlias )
+ {
+ if ( isAntiAlias )
+ {
+ g.SmoothingMode = SmoothingMode.HighQuality;
+ //g.SmoothingMode = SmoothingMode.AntiAlias;
+ g.TextRenderingHint = TextRenderingHint.AntiAlias;
+ g.CompositingQuality = CompositingQuality.HighQuality;
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ }
+ }
+
+ private void MakeImage( Graphics g, int width, int height, bool antiAlias )
+ {
+ //g.SmoothingMode = SmoothingMode.AntiAlias;
+ SetAntiAliasMode( g, antiAlias );
+
+ // This is actually a shallow clone, so we don't duplicate all the data, curveLists, etc.
+ PaneBase tempPane = this.ShallowClone();
+
+ // Clone the Chart object for GraphPanes so we don't mess up the minPix and maxPix values or
+ // the rect/ChartRect calculations of the original
+ //RectangleF saveRect = new RectangleF();
+ //if ( this is GraphPane )
+ // saveRect = ( this as GraphPane ).Chart.Rect;
+
+ tempPane.ReSize( g, new RectangleF( 0, 0, width, height ) );
+
+ tempPane.Draw( g );
+
+ //if ( this is GraphPane )
+ //{
+ // GraphPane gPane = this as GraphPane;
+ // gPane.Chart.Rect = saveRect;
+ // gPane.XAxis.Scale.SetupScaleData( gPane, gPane.XAxis );
+ // foreach ( Axis axis in gPane.YAxisList )
+ // axis.Scale.SetupScaleData( gPane, axis );
+ // foreach ( Axis axis in gPane.Y2AxisList )
+ // axis.Scale.SetupScaleData( gPane, axis );
+ //}
+
+ // To restore all the various state variables, you must redraw the graph in it's
+ // original form. For this we create a 1x1 bitmap (it doesn't matter what size you use,
+ // since we're only mimicing the draw. If you use the 'bitmapGraphics' already created,
+ // then you will be drawing back into the bitmap that will be returned.
+
+ Bitmap bm = new Bitmap( 1, 1 );
+ using ( Graphics bmg = Graphics.FromImage( bm ) )
+ {
+ this.ReSize( bmg, this.Rect );
+ SetAntiAliasMode( bmg, antiAlias );
+ this.Draw( bmg );
+ }
+ }
+
+ /// <summary>
+ /// Gets an enhanced metafile image for the current GraphPane, scaled to the specified size.
+ /// </summary>
+ /// <remarks>
+ /// By definition, a Metafile is a vector drawing, and therefore scaling should not matter.
+ /// However, this method is provided because certain options in Zedgraph, such as
+ /// <see cref="IsFontsScaled" /> are affected by the size of the expected image.
+ /// </remarks>
+ /// <param name="width">The "effective" scaled width of the bitmap in pixels</param>
+ /// <param name="height">The "effective" scaled height of the bitmap in pixels</param>
+ /// <param name="isAntiAlias">true to use anti-aliased drawing mode, false otherwise</param>
+ /// <seealso cref="GetImage()"/>
+ /// <seealso cref="GetImage(int,int,float)"/>
+ /// <seealso cref="GetMetafile()"/>
+ public Metafile GetMetafile( int width, int height, bool isAntiAlias )
+ {
+ Bitmap bm = new Bitmap( 1, 1 );
+ using ( Graphics g = Graphics.FromImage( bm ) )
+ {
+ IntPtr hdc = g.GetHdc();
+ Stream stream = new MemoryStream();
+ Metafile metafile = new Metafile( stream, hdc, _rect,
+ MetafileFrameUnit.Pixel, EmfType.EmfPlusDual );
+ g.ReleaseHdc( hdc );
+
+ using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
+ {
+ //metafileGraphics.TranslateTransform( -_rect.Left, -_rect.Top );
+ metafileGraphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
+ PointF P = new PointF( width, height );
+ PointF[] PA = new PointF[] { P };
+ metafileGraphics.TransformPoints( CoordinateSpace.Page, CoordinateSpace.Device, PA );
+ //metafileGraphics.PageScale = 1f;
+
+ // output
+ MakeImage( metafileGraphics, width, height, isAntiAlias );
+ //this.Draw( metafileGraphics );
+
+ return metafile;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets an enhanced metafile image for the current GraphPane, scaled to the specified size.
+ /// </summary>
+ /// <remarks>
+ /// By definition, a Metafile is a vector drawing, and therefore scaling should not matter.
+ /// However, this method is provided because certain options in Zedgraph, such as
+ /// <see cref="IsFontsScaled" /> are affected by the size of the expected image.
+ /// </remarks>
+ /// <param name="width">The "effective" scaled width of the bitmap in pixels</param>
+ /// <param name="height">The "effective" scaled height of the bitmap in pixels</param>
+ /// <seealso cref="GetImage()"/>
+ /// <seealso cref="GetImage(int,int,float)"/>
+ /// <seealso cref="GetMetafile()"/>
+ public Metafile GetMetafile( int width, int height )
+ {
+ return GetMetafile( width, height, false );
+ }
+
+ /// <summary>
+ /// Gets an enhanced metafile image for the current GraphPane.
+ /// </summary>
+ /// <seealso cref="GetImage()"/>
+ /// <seealso cref="GetImage(int,int,float)"/>
+ /// <seealso cref="GetMetafile(int,int)"/>
+ public Metafile GetMetafile()
+ {
+ Bitmap bm = new Bitmap( 1, 1 );
+ using ( Graphics g = Graphics.FromImage( bm ) )
+ {
+ IntPtr hdc = g.GetHdc();
+ Stream stream = new MemoryStream();
+ Metafile metafile = new Metafile( stream, hdc, _rect,
+ MetafileFrameUnit.Pixel, EmfType.EmfOnly );
+
+ using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
+ {
+ metafileGraphics.TranslateTransform( -_rect.Left, -_rect.Top );
+ metafileGraphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
+ PointF P = new PointF( _rect.Width, _rect.Height );
+ PointF[] PA = new PointF[] { P };
+ metafileGraphics.TransformPoints( CoordinateSpace.Page, CoordinateSpace.Device, PA );
+ //metafileGraphics.PageScale = 1f;
+
+ // output
+ this.Draw( metafileGraphics );
+
+ g.ReleaseHdc( hdc );
+ return metafile;
+ }
+ }
+ }
+
+ /*
+ System.Drawing.Imaging.Metafile metafile = null;
+
+ // create a Metafile object that is compatible with the surface of this
+ // form
+ using ( Graphics graphics = this.CreateGraphics() )
+ {
+ System.IntPtr hdc = graphics.GetHdc();
+ metafile = new Metafile(filename, hdc, new Rectangle( 0, 0,
+ (((int) this.ClientRectangle.Width)),
+ (((int) this.ClientRectangle.Height ))),
+ MetafileFrameUnit.Point );
+ graphics.ReleaseHdc( hdc );
+ }
+
+ // draw to the metafile
+ using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
+ {
+ metafileGraphics.PageUnit=System.Drawing.GraphicsUnit.Point;
+ PointF P=new Point(this.ClientRectangle.Width,this.ClientRectangle.Height);
+ PointF[] PA=new PointF[]{P};
+ metafileGraphics.TransformPoints(CoordinateSpace.Page, CoordinateSpace.Device, PA);
+ metafileGraphics.PageScale=1f;
+ metafileGraphics.SmoothingMode = SmoothingMode.AntiAlias; // smooth the
+ // output
+ this.masterPane.Draw( metafileGraphics );
+ metafileGraphics.DrawRectangle(new System.Drawing.Pen( Color.Gray),this.ClientRectangle);
+ metafile.Dispose();
+
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ //no directory given
+ return false;
+ }
+ */
+
+
+/*
+ /// <summary>
+ /// Function to export the Diagram as WMF file
+ /// see http://www.codeproject.com/showcase/pdfrasterizer.asp?print=true
+ /// </summary>
+ /// <param name="filename">
+ /// filename is the name to export to
+ /// </param>
+ public bool ExporttoWmf( string filename )
+ {
+ string p;
+
+ //FileInfo TheFile = new FileInfo(filename);
+ p = Path.GetDirectoryName( filename );
+ if ( p != "" )
+ {
+ DirectoryInfo TheDir = new DirectoryInfo( p );
+ if ( TheDir.Exists )
+ {
+ System.Drawing.Imaging.Metafile metafile = null;
+
+ // create a Metafile object that is compatible with the surface of this
+ // form
+ using ( Graphics graphics = this.CreateGraphics() )
+ {
+ System.IntPtr hdc = graphics.GetHdc();
+ metafile = new Metafile( filename, hdc, new Rectangle( 0, 0,
+ ( ( (int)this.ClientRectangle.Width ) ),
+ ( ( (int)this.ClientRectangle.Height ) ) ),
+ MetafileFrameUnit.Point );
+ graphics.ReleaseHdc( hdc );
+ }
+
+ // draw to the metafile
+ using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
+ {
+ metafileGraphics.PageUnit = System.Drawing.GraphicsUnit.Point;
+ PointF P = new Point( this.ClientRectangle.Width, this.ClientRectangle.Height );
+ PointF[] PA = new PointF[] { P };
+ metafileGraphics.TransformPoints( CoordinateSpace.Page, CoordinateSpace.Device, PA );
+ metafileGraphics.PageScale = 1f;
+ metafileGraphics.SmoothingMode = SmoothingMode.AntiAlias; // smooth the
+ // output
+ this.masterPane.Draw( metafileGraphics );
+ metafileGraphics.DrawRectangle( new System.Drawing.Pen( Color.Gray ), this.ClientRectangle );
+ metafile.Dispose();
+
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ //no directory given
+ return false;
+ }
+ }
+ */
+ internal PointF TransformCoord( double x, double y, CoordType coord )
+ {
+ // If the Transformation is an illegal type, just stick it in the middle
+ if ( !( this is GraphPane ) && !( coord == CoordType.PaneFraction ) )
+ {
+ coord = CoordType.PaneFraction;
+ x = 0.5;
+ y = 0.5;
+ }
+
+ // Just to save some casts
+ GraphPane gPane = null;
+ RectangleF chartRect = new RectangleF( 0, 0, 1, 1 );
+ if ( this is GraphPane )
+ {
+ gPane = this as GraphPane;
+ chartRect = gPane.Chart._rect;
+ }
+
+ PointF ptPix = new PointF();
+
+ if ( coord == CoordType.ChartFraction )
+ {
+ ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
+ ptPix.Y = (float)( chartRect.Top + y * chartRect.Height );
+ }
+ else if ( coord == CoordType.AxisXYScale )
+ {
+ ptPix.X = gPane.XAxis.Scale.Transform( x );
+ ptPix.Y = gPane.YAxis.Scale.Transform( y );
+ }
+ else if ( coord == CoordType.AxisXY2Scale )
+ {
+ ptPix.X = gPane.XAxis.Scale.Transform( x );
+ ptPix.Y = gPane.Y2Axis.Scale.Transform( y );
+ }
+ else if ( coord == CoordType.XScaleYChartFraction )
+ {
+ ptPix.X = gPane.XAxis.Scale.Transform( x );
+ ptPix.Y = (float)( chartRect.Top + y * chartRect.Height );
+ }
+ else if ( coord == CoordType.XChartFractionYScale )
+ {
+ ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
+ ptPix.Y = gPane.YAxis.Scale.Transform( y );
+ }
+ else if ( coord == CoordType.XChartFractionY2Scale )
+ {
+ ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
+ ptPix.Y = gPane.Y2Axis.Scale.Transform( y );
+ }
+ else if ( coord == CoordType.XChartFractionYPaneFraction )
+ {
+ ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
+ ptPix.Y = (float)( this.Rect.Top + y * _rect.Height );
+ }
+ else if ( coord == CoordType.XPaneFractionYChartFraction )
+ {
+ ptPix.X = (float)( this.Rect.Left + x * _rect.Width );
+ ptPix.Y = (float)( chartRect.Top + y * chartRect.Height );
+ }
+ else // PaneFraction
+ {
+ ptPix.X = (float)( _rect.Left + x * _rect.Width );
+ ptPix.Y = (float)( _rect.Top + y * _rect.Height );
+ }
+
+ return ptPix;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PaneLayoutMgr.cs b/ZedGraph/PaneLayoutMgr.cs
new file mode 100644
index 0000000..8be04f9
--- /dev/null
+++ b/ZedGraph/PaneLayoutMgr.cs
@@ -0,0 +1,560 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright (C) 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// internal class to store pane layout details for the <see cref="MasterPane" />
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public class PaneLayoutMgr : ICloneable, ISerializable
+ {
+ // =========== PANE LAYOUT STUFF ================
+
+ #region Fields
+
+ /// <summary>
+ /// private field that saves the paneLayout format specified when
+ /// <see cref="SetLayout(PaneLayout)"/> was called. This value will
+ /// default to <see cref="MasterPane.Default.PaneLayout"/> if
+ /// <see cref="SetLayout(PaneLayout)"/> (or an overload) was never called.
+ /// </summary>
+ internal PaneLayout _paneLayout;
+
+ /// <summary>
+ /// Private field that stores the boolean value that determines whether
+ /// <see cref="_countList"/> is specifying rows or columns.
+ /// </summary>
+ internal bool _isColumnSpecified;
+ /// <summary>
+ /// private field that stores the row/column item count that was specified to the
+ /// <see cref="SetLayout(bool,int[],float[])"/> method. This values will be
+ /// null if <see cref="SetLayout(bool,int[],float[])"/> was never called.
+ /// </summary>
+ internal int[] _countList;
+
+ /// <summary>
+ /// private field that stores the row/column size proportional values as specified
+ /// to the <see cref="SetLayout(bool,int[],float[])"/> method. This
+ /// value will be null if <see cref="SetLayout(bool,int[],float[])"/>
+ /// was never called.
+ /// </summary>
+ internal float[] _prop;
+
+ #endregion
+
+ #region Constructors
+
+ internal void Init()
+ {
+ _paneLayout = MasterPane.Default.PaneLayout;
+ _countList = null;
+ _isColumnSpecified = false;
+ _prop = null;
+ }
+
+ internal PaneLayoutMgr()
+ {
+ Init();
+ }
+
+ internal PaneLayoutMgr( PaneLayoutMgr rhs )
+ {
+ _paneLayout = rhs._paneLayout;
+ _countList = rhs._countList;
+ _isColumnSpecified = rhs._isColumnSpecified;
+ _prop = rhs._prop;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public PaneLayoutMgr Clone()
+ {
+ return new PaneLayoutMgr( this );
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ internal const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ public PaneLayoutMgr( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _paneLayout = (PaneLayout)info.GetValue( "paneLayout", typeof( PaneLayout ) );
+ _countList = (int[])info.GetValue( "countList", typeof(int[]) );
+
+ _isColumnSpecified = info.GetBoolean( "isColumnSpecified" );
+ _prop = (float[]) info.GetValue( "prop", typeof( float[] ) );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+
+ info.AddValue( "paneLayout", _paneLayout );
+ info.AddValue( "countList", _countList );
+ info.AddValue( "isColumnSpecified", _isColumnSpecified );
+ info.AddValue( "prop", _prop );
+ }
+ #endregion
+
+ #region Methods
+
+ /// <overloads>The SetLayout() methods setup the desired layout of the
+ /// <see cref="GraphPane" /> objects within a <see cref="MasterPane" />. These functions
+ /// do not make any changes, they merely set the parameters so that future calls
+ /// to <see cref="PaneBase.ReSize" /> or <see cref="DoLayout(Graphics,MasterPane)" />
+ /// will use the desired layout.<br /><br />
+ /// The layout options include a set of "canned" layouts provided by the
+ /// <see cref="ZedGraph.PaneLayout" /> enumeration, options to just set a specific
+ /// number of rows and columns of panes (and all pane sizes are the same), and more
+ /// customized options of specifying the number or rows in each column or the number of
+ /// columns in each row, along with proportional values that determine the size of each
+ /// individual column or row.
+ /// </overloads>
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to a pre-defined layout configuration from a <see cref="PaneLayout" />
+ /// enumeration.
+ /// </summary>
+ /// <remarks>This method uses a <see cref="PaneLayout"/> enumeration to describe the type of layout
+ /// to be used. Overloads are available that provide other layout options</remarks>
+ /// <param name="paneLayout">A <see cref="PaneLayout"/> enumeration that describes how
+ /// the panes should be laid out within the <see cref="PaneBase.Rect"/>.</param>
+ /// <seealso cref="SetLayout(int,int)" />
+ /// <seealso cref="SetLayout(bool,int[])" />
+ /// <seealso cref="SetLayout(bool,int[],float[])" />
+ public void SetLayout( PaneLayout paneLayout )
+ {
+ Init();
+
+ _paneLayout = paneLayout;
+ }
+
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to a reasonable configuration.
+ /// </summary>
+ /// <remarks>This method explicitly specifies the number of rows and columns to use
+ /// in the layout, and all <see cref="GraphPane" /> objects will have the same size.
+ /// Overloads are available that provide other layout options</remarks>
+ /// <param name="rows">The number of rows of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ /// <param name="columns">The number of columns of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ /// <seealso cref="SetLayout(PaneLayout)" />
+ /// <seealso cref="SetLayout(bool,int[])" />
+ /// <seealso cref="SetLayout(bool,int[],float[])" />
+ public void SetLayout( int rows, int columns )
+ {
+ Init();
+
+ if ( rows < 1 )
+ rows = 1;
+ if ( columns < 1 )
+ columns = 1;
+
+ int[] countList = new int[rows];
+
+ for (int i=0; i<rows; i++ )
+ countList[i] = columns;
+
+ SetLayout( true, countList, null );
+ }
+
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to the specified configuration.
+ /// </summary>
+ /// <remarks>This method specifies the number of rows in each column, or the number of
+ /// columns in each row, allowing for irregular layouts. Overloads are available that
+ /// provide other layout options.
+ /// </remarks>
+ /// <param name="isColumnSpecified">Specifies whether the number of columns in each row, or
+ /// the number of rows in each column will be specified. A value of true indicates the
+ /// number of columns in each row are specified in <see paramref="countList"/>.</param>
+ /// <param name="countList">An integer array specifying either the number of columns in
+ /// each row or the number of rows in each column, depending on the value of
+ /// <see paramref="isColumnSpecified"/>.</param>
+ /// <seealso cref="SetLayout(PaneLayout)" />
+ /// <seealso cref="SetLayout(int,int)" />
+ /// <seealso cref="SetLayout(bool,int[],float[])" />
+ public void SetLayout( bool isColumnSpecified, int[] countList )
+ {
+ SetLayout( isColumnSpecified, countList, null );
+ }
+
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to the specified configuration.
+ /// </summary>
+ /// <remarks>This method specifies the number of panes in each row or column, allowing for
+ /// irregular layouts.</remarks>
+ /// <remarks>This method specifies the number of rows in each column, or the number of
+ /// columns in each row, allowing for irregular layouts. Additionally, a
+ /// <see paramref="proportion" /> parameter is provided that allows varying column or
+ /// row sizes. Overloads for SetLayout() are available that provide other layout options.
+ /// </remarks>
+ /// <param name="isColumnSpecified">Specifies whether the number of columns in each row, or
+ /// the number of rows in each column will be specified. A value of true indicates the
+ /// number of columns in each row are specified in <see paramref="_countList"/>.</param>
+ /// <param name="countList">An integer array specifying either the number of columns in
+ /// each row or the number of rows in each column, depending on the value of
+ /// <see paramref="isColumnSpecified"/>.</param>
+ /// <param name="proportion">An array of float values specifying proportional sizes for each
+ /// row or column. Note that these proportions apply to the non-specified dimension -- that is,
+ /// if <see paramref="isColumnSpecified"/> is true, then these proportions apply to the row
+ /// heights, and if <see paramref="isColumnSpecified"/> is false, then these proportions apply
+ /// to the column widths. The values in this array are arbitrary floats -- the dimension of
+ /// any given row or column is that particular proportional value divided by the sum of all
+ /// the values. For example, let <see paramref="isColumnSpecified"/> be true, and
+ /// <see paramref="proportion"/> is an array with values of { 1.0, 2.0, 3.0 }. The sum of
+ /// those values is 6.0. Therefore, the first row is 1/6th of the available height, the
+ /// second row is 2/6th's of the available height, and the third row is 3/6th's of the
+ /// available height.
+ /// </param>
+ /// <seealso cref="SetLayout(PaneLayout)" />
+ /// <seealso cref="SetLayout(int,int)" />
+ /// <seealso cref="SetLayout(bool,int[])" />
+ public void SetLayout( bool isColumnSpecified, int[] countList, float[] proportion )
+ {
+ Init();
+
+ // use defaults if the parameters are invalid
+ if ( countList != null && countList.Length > 0 )
+ {
+ this._prop = new float[countList.Length];
+
+ // Sum up the total proportional factors
+ float sumProp = 0.0f;
+ for ( int i = 0; i < countList.Length; i++ )
+ {
+ this._prop[i] = ( proportion == null || proportion.Length <= i || proportion[i] < 1e-10 ) ?
+ 1.0f : proportion[i];
+ sumProp += this._prop[i];
+ }
+
+ // Make prop sum to 1.0
+ for ( int i=0; i<countList.Length; i++ )
+ this._prop[i] /= sumProp;
+
+ _isColumnSpecified = isColumnSpecified;
+ _countList = countList;
+ }
+ }
+
+ /// <summary>
+ /// Modify the <see cref="GraphPane" /> <see cref="PaneBase.Rect" /> sizes of each
+ /// <see cref="GraphPane" /> such that they fit within the <see cref="MasterPane" />
+ /// in a pre-configured layout.
+ /// </summary>
+ /// <remarks>The <see cref="SetLayout(PaneLayout)" /> method (and overloads) is
+ /// used for setting the layout configuration.</remarks>
+ /// <param name="g">A <see cref="Graphics" /> instance to be used for font sizing,
+ /// etc. in determining the layout configuration.</param>
+ /// <param name="master">The <see cref="MasterPane" /> instance which is to
+ /// be resized.</param>
+ /// <seealso cref="SetLayout(PaneLayout)" />
+ /// <seealso cref="SetLayout(int,int)" />
+ /// <seealso cref="SetLayout(bool,int[])" />
+ /// <seealso cref="SetLayout(bool,int[],float[])" />
+ public void DoLayout( Graphics g, MasterPane master )
+ {
+ if ( this._countList != null )
+ DoLayout( g, master, this._isColumnSpecified, this._countList, this._prop );
+ else
+ {
+ int count = master.PaneList.Count;
+ if ( count == 0 )
+ return;
+
+ int rows,
+ cols,
+ root = (int)( Math.Sqrt( (double)count ) + 0.9999999 );
+
+ //float[] widthList = new float[5];
+
+ switch ( _paneLayout )
+ {
+ case PaneLayout.ForceSquare:
+ rows = root;
+ cols = root;
+ DoLayout( g, master, rows, cols );
+ break;
+ case PaneLayout.SingleColumn:
+ rows = count;
+ cols = 1;
+ DoLayout( g, master, rows, cols );
+ break;
+ case PaneLayout.SingleRow:
+ rows = 1;
+ cols = count;
+ DoLayout( g, master, rows, cols );
+ break;
+ default:
+ case PaneLayout.SquareColPreferred:
+ rows = root;
+ cols = root;
+ if ( count <= root * ( root - 1 ) )
+ rows--;
+ DoLayout( g, master, rows, cols );
+ break;
+ case PaneLayout.SquareRowPreferred:
+ rows = root;
+ cols = root;
+ if ( count <= root * ( root - 1 ) )
+ cols--;
+ DoLayout( g, master, rows, cols );
+ break;
+ case PaneLayout.ExplicitCol12:
+ DoLayout( g, master, true, new int[2] { 1, 2 }, null );
+ break;
+ case PaneLayout.ExplicitCol21:
+ DoLayout( g, master, true, new int[2] { 2, 1 }, null );
+ break;
+ case PaneLayout.ExplicitCol23:
+ DoLayout( g, master, true, new int[2] { 2, 3 }, null );
+ break;
+ case PaneLayout.ExplicitCol32:
+ DoLayout( g, master, true, new int[2] { 3, 2 }, null );
+ break;
+ case PaneLayout.ExplicitRow12:
+ DoLayout( g, master, false, new int[2] { 1, 2 }, null );
+ break;
+ case PaneLayout.ExplicitRow21:
+ DoLayout( g, master, false, new int[2] { 2, 1 }, null );
+ break;
+ case PaneLayout.ExplicitRow23:
+ DoLayout( g, master, false, new int[2] { 2, 3 }, null );
+ break;
+ case PaneLayout.ExplicitRow32:
+ DoLayout( g, master, false, new int[2] { 3, 2 }, null );
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Internal method that applies a previously set layout with a specific
+ /// row and column count. This method is only called by
+ /// <see cref="DoLayout(Graphics,MasterPane)" />.
+ /// </summary>
+ internal void DoLayout( Graphics g, MasterPane master, int rows, int columns )
+ {
+ if ( rows < 1 )
+ rows = 1;
+ if ( columns < 1 )
+ columns = 1;
+
+ int[] countList = new int[rows];
+
+ for (int i=0; i<rows; i++ )
+ countList[i] = columns;
+
+ DoLayout( g, master, true, countList, null );
+ }
+
+ /// <summary>
+ /// Internal method that applies a previously set layout with a rows per column or
+ /// columns per row configuration. This method is only called by
+ /// <see cref="DoLayout(Graphics,MasterPane)" />.
+ /// </summary>
+ internal void DoLayout( Graphics g, MasterPane master, bool isColumnSpecified, int[] countList,
+ float[] proportion )
+ {
+
+ // calculate scaleFactor on "normal" pane size (BaseDimension)
+ float scaleFactor = master.CalcScaleFactor();
+
+ // innerRect is the area for the GraphPane's
+ RectangleF innerRect = master.CalcClientRect( g, scaleFactor );
+ master.Legend.CalcRect( g, master, scaleFactor, ref innerRect );
+
+ // scaled InnerGap is the area between the GraphPane.Rect's
+ float scaledInnerGap = (float)( master._innerPaneGap * scaleFactor );
+
+ int iPane = 0;
+
+ if ( isColumnSpecified )
+ {
+ int rows = countList.Length;
+
+ float y = 0.0f;
+
+ for ( int rowNum = 0; rowNum < rows; rowNum++ )
+ {
+ float propFactor = _prop == null ? 1.0f / rows : _prop[rowNum];
+
+ float height = ( innerRect.Height - (float)( rows - 1 ) * scaledInnerGap ) *
+ propFactor;
+
+ int columns = countList[rowNum];
+ if ( columns <= 0 )
+ columns = 1;
+ float width = ( innerRect.Width - (float)( columns - 1 ) * scaledInnerGap ) /
+ (float)columns;
+
+ if ( iPane >= master._paneList.Count )
+ return;
+
+ for ( int colNum = 0; colNum < columns; colNum++ )
+ {
+ master[iPane].Rect = new RectangleF(
+ innerRect.X + colNum * ( width + scaledInnerGap ),
+ innerRect.Y + y,
+ width,
+ height );
+ iPane++;
+ }
+
+ y += height + scaledInnerGap;
+ }
+ }
+ else
+ {
+ int columns = countList.Length;
+
+ float x = 0.0f;
+
+ for ( int colNum = 0; colNum < columns; colNum++ )
+ {
+ float propFactor = _prop == null ? 1.0f / columns : _prop[colNum];
+
+ float width = ( innerRect.Width - (float)( columns - 1 ) * scaledInnerGap ) *
+ propFactor;
+
+ int rows = countList[colNum];
+ if ( rows <= 0 )
+ rows = 1;
+ float height = ( innerRect.Height - (float)( rows - 1 ) * scaledInnerGap ) / (float)rows;
+
+ for ( int rowNum = 0; rowNum < rows; rowNum++ )
+ {
+ if ( iPane >= master._paneList.Count )
+ return;
+
+ master[iPane].Rect = new RectangleF(
+ innerRect.X + x,
+ innerRect.Y + rowNum * ( height + scaledInnerGap ),
+ width,
+ height );
+ iPane++;
+ }
+
+ x += width + scaledInnerGap;
+ }
+ }
+ }
+
+ /*
+ /// <summary>
+ /// Automatically set all of the <see cref="GraphPane"/> <see cref="PaneBase.Rect"/>'s in
+ /// the list to a reasonable configuration.
+ /// </summary>
+ /// <remarks>This method explicitly specifies the number of rows and columns to use in the layout.
+ /// A more automatic overload, using a <see cref="PaneLayout"/> enumeration, is available.</remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rows">The number of rows of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ /// <param name="columns">The number of columns of <see cref="GraphPane"/> objects
+ /// to include in the layout</param>
+ public void DoPaneLayout( Graphics g, int rows, int columns )
+ {
+ // save the layout settings for future reference
+ this._countList = null;
+ this._rows = rows;
+ this._columns = columns;
+
+ // calculate scaleFactor on "normal" pane size (BaseDimension)
+ float scaleFactor = this.CalcScaleFactor();
+
+ // innerRect is the area for the GraphPane's
+ RectangleF innerRect = CalcClientRect( g, scaleFactor );
+ this._legend.CalcRect( g, this, scaleFactor, ref innerRect );
+
+ // scaled InnerGap is the area between the GraphPane.Rect's
+ float scaledInnerGap = (float)( this._innerPaneGap * scaleFactor );
+
+ float width = ( innerRect.Width - (float)( columns - 1 ) * scaledInnerGap ) / (float)columns;
+ float height = ( innerRect.Height - (float)( rows - 1 ) * scaledInnerGap ) / (float)rows;
+
+ int i = 0;
+ foreach ( GraphPane pane in this._paneList )
+ {
+ float rowNum = (float)( i / columns );
+ float colNum = (float)( i % columns );
+
+ pane.Rect = new RectangleF(
+ innerRect.X + colNum * ( width + scaledInnerGap ),
+ innerRect.Y + rowNum * ( height + scaledInnerGap ),
+ width,
+ height );
+
+ i++;
+ }
+ }
+ */
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PaneList.cs b/ZedGraph/PaneList.cs
new file mode 100644
index 0000000..d5adc44
--- /dev/null
+++ b/ZedGraph/PaneList.cs
@@ -0,0 +1,236 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="GraphPane"/> objects.
+ /// </summary>
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.6 $ $Date: 2006-06-24 20:26:43 $ </version>
+ [Serializable]
+ public class PaneList : List<GraphPane>, ICloneable
+ {
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the collection class.
+ /// </summary>
+ public PaneList()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="PaneList"/> object from which to copy</param>
+ public PaneList( PaneList rhs )
+ {
+ foreach ( GraphPane item in rhs )
+ {
+ this.Add( item.Clone() );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public PaneList Clone()
+ {
+ return new PaneList( this );
+ }
+
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PaneList( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ }
+ #endregion
+
+ #region List Methods
+/* /// <summary>
+ /// Indexer to access the specified <see cref="GraphPane"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="GraphPane"/> object to be accessed.</param>
+ /// <value>A <see cref="GraphPane"/> object reference.</value>
+ public GraphPane this[ int index ]
+ {
+ get { return( (GraphPane) List[index] ); }
+ set { List[index] = value; }
+ }
+*/
+ /// <summary>
+ /// Indexer to access the specified <see cref="GraphPane"/> object by
+ /// its <see cref="PaneBase.Title"/> string.
+ /// </summary>
+ /// <param name="title">The string title of the
+ /// <see cref="GraphPane"/> object to be accessed.</param>
+ /// <value>A <see cref="GraphPane"/> object reference.</value>
+ public GraphPane this[ string title ]
+ {
+ get
+ {
+ int index = IndexOf( title );
+ if ( index >= 0 )
+ return( (GraphPane) this[index] );
+ else
+ return null;
+ }
+ }
+/*
+ /// <summary>
+ /// Add a <see cref="GraphPane"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object to
+ /// be added</param>
+ /// <seealso cref="IList.Add"/>
+ public void Add( GraphPane pane )
+ {
+ List.Add( pane );
+ }
+
+ /// <summary>
+ /// Remove a <see cref="GraphPane"/> object from the collection based on an object reference.
+ /// </summary>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that is to be
+ /// removed.</param>
+ /// <seealso cref="IList.Remove"/>
+ public void Remove( GraphPane pane )
+ {
+ List.Remove( pane );
+ }
+
+ /// <summary>
+ /// Insert a <see cref="GraphPane"/> object into the collection at the specified
+ /// zero-based index location.
+ /// </summary>
+ /// <param name="index">The zero-based index location for insertion.</param>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object that is to be
+ /// inserted.</param>
+ /// <seealso cref="IList.Insert"/>
+ public void Insert( int index, GraphPane pane )
+ {
+ List.Insert( index, pane );
+ }
+*/
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="GraphPane"/> with the specified <see cref="PaneBase.Title"/>.
+ /// </summary>
+ /// <remarks>The comparison of titles is not case sensitive, but it must include
+ /// all characters including punctuation, spaces, etc.</remarks>
+ /// <param name="title">The <see cref="String"/> label that is in the
+ /// <see cref="PaneBase.Title"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="GraphPane"/>,
+ /// or -1 if the <see cref="PaneBase.Title"/> was not found in the list</returns>
+ /// <seealso cref="IndexOfTag"/>
+ public int IndexOf( string title )
+ {
+ int index = 0;
+ foreach ( GraphPane pane in this )
+ {
+ if ( String.Compare( pane.Title.Text, title, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="GraphPane"/> with the specified <see cref="PaneBase.Tag"/>.
+ /// </summary>
+ /// <remarks>In order for this method to work, the <see cref="PaneBase.Tag"/>
+ /// property must be of type <see cref="String"/>.</remarks>
+ /// <param name="tagStr">The <see cref="String"/> tag that is in the
+ /// <see cref="PaneBase.Tag"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="GraphPane"/>,
+ /// or -1 if the <see cref="PaneBase.Tag"/> string is not in the list</returns>
+ public int IndexOfTag( string tagStr )
+ {
+ int index = 0;
+ foreach ( GraphPane pane in this )
+ {
+ if ( pane.Tag is string &&
+ String.Compare( (string) pane.Tag, tagStr, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PieItem.cs b/ZedGraph/PieItem.cs
new file mode 100644
index 0000000..4438833
--- /dev/null
+++ b/ZedGraph/PieItem.cs
@@ -0,0 +1,1090 @@
+//============================================================================
+//PieItem Class
+//Copyright � 2005 Bob Kaye
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.Drawing.Drawing2D;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class representing a pie chart object comprised of one or more
+ /// <see cref="PieItem"/>s.
+ /// </summary>
+ /// <author> Bob Kaye </author>
+ /// <version> $Revision: 1.32 $ $Date: 2007-07-30 05:26:23 $ </version>
+ [Serializable]
+ public class PieItem : CurveItem, ICloneable, ISerializable
+ {
+
+ #region Fields
+ /*
+ /// <summary>
+ /// Private field instance of the <see cref="PieItem"/> class indicating whether
+ /// the instance is displayed in 2D or 3D.(see <see cref="PieItem.PieType"/>)
+ /// </summary>
+ private PieType pieType;
+*/
+ /// <summary>
+ /// Percentage (expressed as #.##) of <see cref="PieItem"/> radius to
+ /// which this <see cref="PieItem"/> is to be displaced from the center.
+ /// Displacement is done outward along the radius
+ /// bisecting the chord of this <see cref="PieItem"/>. Maximum allowable value
+ /// is 0.5.
+ /// </summary>
+ private double _displacement;
+
+ /// <summary>
+ /// A <see cref="ZedGraph.TextObj"/> which will customize the label display of this
+ /// <see cref="PieItem"/>
+ /// </summary>
+ private TextObj _labelDetail;
+
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="PieItem"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+
+ /// <summary>
+ /// Private field that stores the <see cref="Border"/> class that defines the
+ /// properties of the border around this <see cref="PieItem"/>. Use the public
+ /// property <see cref="Border"/> to access this value.
+ /// </summary>
+ private Border _border;
+
+ /// <summary>
+ /// Private field that stores the absolute value of this <see cref="PieItem"/> instance.
+ /// Value will be set to zero if submitted value is less than zero.
+ /// </summary>
+ private double _pieValue;
+
+ /// <summary>
+ /// An enum that specifies how each <see cref="CurveItem.Label"/> for this <see cref="PieItem"/> object
+ /// will be displayed. Use the public property <see cref="LabelType"/> to access this data.
+ /// Use enum <see cref="ZedGraph.PieLabelType"/>.
+ /// </summary>
+ private PieLabelType _labelType;
+ /// <summary>
+ /// The point on the arc of this <see cref="PieItem"/> representing the intersection of
+ /// the arc and the explosion radius.
+ /// </summary>
+ private PointF _intersectionPoint;
+
+ /// <summary>
+ /// The bounding rectangle for this <see cref="PieItem"/>.
+ /// </summary>
+ private RectangleF _boundingRectangle;
+
+ /// <summary>
+ /// The formatted string for this <see cref="PieItem"/>'s label. Formatting is
+ /// done based on the <see cref="PieLabelType"/>.
+ /// </summary>
+ private string _labelStr;
+ /// <summary>
+ /// The point at which the line between this <see cref="PieItem"/> and its
+ /// label bends to the horizontal.
+ /// </summary>
+ private PointF _pivotPoint;
+ /// <summary>
+ /// The point at the end of the line between this <see cref="PieItem"/> and
+ /// it's label (i.e. the beginning of the label display)
+ /// </summary>
+ private PointF _endPoint;
+
+ /// <summary>
+ /// Private field to hold the GraphicsPath of this <see cref="PieItem"/> to be
+ /// used for 'hit testing'.
+ /// </summary>
+ private GraphicsPath _slicePath;
+
+ /// <summary>
+ /// Private field which holds the angle (in degrees) at which the display of this <see cref="PieItem"/>
+ /// object will begin.
+ /// </summary>
+ private float _startAngle;
+
+ /// <summary>
+ ///Private field which holds the length (in degrees) of the arc representing this <see cref="PieItem"/>
+ ///object.
+ /// </summary>
+ private float _sweepAngle;
+
+ /// <summary>
+ ///Private field which represents the angle (in degrees) of the radius along which this <see cref="PieItem"/>
+ ///object will be displaced, if desired.
+ /// </summary>
+ private float _midAngle;
+
+ /// <summary>
+ ///Private field which determines the number of decimal digits displayed to
+ ///in a <see cref="PieItem"/> label containing a value.
+ /// </summary>
+ private int _valueDecimalDigits;
+
+ /// <summary>
+ ///Private field which determines the number of decimal digits displayed
+ ///in a <see cref="PieItem"/> label containing a percent.
+ /// </summary>
+ private int _percentDecimalDigits;
+
+ private static ColorSymbolRotator _rotator = new ColorSymbolRotator();
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// Specify the default property values for the <see cref="PieItem"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ ///Default <see cref="PieItem "/> displacement.
+ /// </summary>
+ public static double Displacement = 0;
+
+ /// <summary>
+ /// The default pen width to be used for drawing the border around the PieItem
+ /// (<see cref="ZedGraph.LineBase.Width"/> property). Units are points.
+ /// </summary>
+ public static float BorderWidth = 1.0F;
+ /// <summary>
+ /// The default fill mode for this PieItem (<see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FillType = FillType.Brush;
+ /// <summary>
+ /// The default border mode for PieItem (<see cref="ZedGraph.LineBase.IsVisible"/> property).
+ /// true to display frame around PieItem, false otherwise
+ /// </summary>
+ public static bool IsBorderVisible = true;
+ /// <summary>
+ /// The default color for drawing frames around PieItem
+ /// (<see cref="ZedGraph.LineBase.Color"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Black;
+ /// <summary>
+ /// The default color for filling in the PieItem
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.Red;
+ /// <summary>
+ /// The default custom brush for filling in the PieItem.
+ /// (<see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null;
+
+ /// <summary>
+ ///Default value for controlling <see cref="PieItem"/> display.
+ /// </summary>
+ public static bool isVisible = true;
+
+ /// <summary>
+ /// Default value for <see cref="PieItem.LabelType"/>.
+ /// </summary>
+ public static PieLabelType LabelType = PieLabelType.Name;
+
+ /// <summary>
+ /// The default font size for <see cref="PieItem.LabelDetail"/> entries
+ /// (<see cref="ZedGraph.FontSpec.Size"/> property). Units are
+ /// in points (1/72 inch).
+ /// </summary>
+ public static float FontSize = 10;
+
+ /// <summary>
+ /// Default value for the number of decimal digits
+ /// to be displayed when <see cref="LabelType"/> contains a value.
+ /// </summary>
+ public static int ValueDecimalDigits = 0;
+
+ /// <summary>
+ /// Default value for the number of decimal digits
+ /// to be displayed where <see cref="LabelType"/> contains a percent.
+ /// </summary>
+ public static int PercentDecimalDigits = 2;
+ }
+ #endregion Defaults
+
+ #region PieItem Properties
+ /// <summary>
+ /// Gets or sets the a value which determines the amount, if any, of this <see cref="PieItem"/>
+ /// displacement.
+ /// </summary>
+ public double Displacement
+ {
+ get { return ( _displacement ); }
+ set { _displacement = value > .5 ? .5 : value; }
+ }
+
+ /// <summary>
+ /// Gets a path representing this <see cref="PieItem"/>
+ /// </summary>
+ public GraphicsPath SlicePath
+ {
+ get { return _slicePath; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="TextObj"/> to be used
+ /// for displaying this <see cref="PieItem"/>'s label.
+ /// </summary>
+ public TextObj LabelDetail
+ {
+ get { return _labelDetail; }
+ set { _labelDetail = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="Border"/> object so as to be able to modify
+ /// its properties.
+ /// </summary>
+ public Border Border
+ {
+ get { return ( _border ); }
+ set { _border = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="Fill" /> object which is used to fill the
+ /// pie slice with color.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the arc length (in degrees) of this <see cref="PieItem"/>.
+ /// </summary>
+ private float SweepAngle
+ {
+ get { return _sweepAngle; }
+ set { _sweepAngle = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the starting angle (in degrees) of this <see cref="PieItem"/>.
+ /// </summary>
+ private float StartAngle
+ {
+ get { return ( _startAngle ); }
+ set { _startAngle = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the angle (in degrees) of the radius along which
+ /// this <see cref="PieItem"/> will be displaced.
+ /// </summary>
+ private float MidAngle
+ {
+ get { return ( _midAngle ); }
+ set { _midAngle = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of this <see cref="PieItem"/>.
+ /// Minimum value is 0.
+ /// </summary>
+ public double Value
+ {
+ get { return ( _pieValue ); }
+ set { _pieValue = value > 0 ? value : 0; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="PieLabelType"/> to be used in displaying
+ /// <see cref="PieItem"/> labels.
+ /// </summary>
+ public PieLabelType LabelType
+ {
+ get { return ( _labelType ); }
+ set
+ {
+ _labelType = value;
+ if ( value == PieLabelType.None )
+ this.LabelDetail.IsVisible = false;
+ else
+ this.LabelDetail.IsVisible = true;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of decimal digits to be displayed in a <see cref="PieItem"/>
+ /// value label.
+ /// </summary>
+ public int ValueDecimalDigits
+ {
+ get { return ( _valueDecimalDigits ); }
+ set { _valueDecimalDigits = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of decimal digits to be displayed in a <see cref="PieItem"/>
+ /// percent label.
+ /// </summary>
+ public int PercentDecimalDigits
+ {
+ get { return ( _percentDecimalDigits ); }
+ set { _percentDecimalDigits = value; }
+ }
+
+ /*
+ /// <summary>
+ /// Getsor sets enum <see cref="PieType"/> to be used for drawing this <see cref="PieItem"/>.
+ /// </summary>
+ public PieType PieType
+ {
+ get { return (this.pieType); }
+ set { this.pieType = value; }
+ }
+ */
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return true;
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="PieItem"/>, providing a gradient fill for the pie color.
+ /// </summary>
+ /// <param name="pieValue">The value associated with this <see cref="PieItem"/> instance.</param>
+ /// <param name="color1">The starting display color for the gradient <see cref="Fill"/> for this
+ /// <see cref="PieItem"/> instance.</param>
+ /// <param name="color2">The ending display color for the gradient <see cref="Fill"/> for this
+ /// <see cref="PieItem"/> instance.</param>
+ /// <param name="fillAngle">The angle for the gradient <see cref="Fill"/>.</param>
+ /// <param name="displacement">The amount this <see cref="PieItem"/> instance will be
+ /// displaced from the center point.</param>
+ /// <param name="label">Text label for this <see cref="PieItem"/> instance.</param>
+ public PieItem( double pieValue, Color color1, Color color2, float fillAngle,
+ double displacement, string label )
+ :
+ this( pieValue, color1, displacement, label )
+ {
+ if ( !color1.IsEmpty && !color2.IsEmpty )
+ _fill = new Fill( color1, color2, fillAngle );
+ }
+
+ /// <summary>
+ /// Create a new <see cref="PieItem"/>.
+ /// </summary>
+ /// <param name="pieValue">The value associated with this <see cref="PieItem"/> instance.</param>
+ /// <param name="color">The display color for this <see cref="PieItem"/> instance.</param>
+ /// <param name="displacement">The amount this <see cref="PieItem"/> instance will be
+ /// displaced from the center point.</param>
+ /// <param name="label">Text label for this <see cref="PieItem"/> instance.</param>
+ public PieItem( double pieValue, Color color, double displacement, string label )
+ : base( label )
+ {
+ _pieValue = pieValue;
+ _fill = new Fill( color.IsEmpty ? _rotator.NextColor : color );
+ _displacement = displacement;
+ _border = new Border( Default.BorderColor, Default.BorderWidth );
+ _labelDetail = new TextObj();
+ _labelDetail.FontSpec.Size = Default.FontSize;
+ _labelType = Default.LabelType;
+ _valueDecimalDigits = Default.ValueDecimalDigits;
+ _percentDecimalDigits = Default.PercentDecimalDigits;
+ _slicePath = null;
+ }
+
+ /// <summary>
+ /// Create a new <see cref="PieItem"/>.
+ /// </summary>
+ /// <param name="pieValue">The value associated with this <see cref="PieItem"/> instance.</param>
+ /// <param name="label">Text label for this <see cref="PieItem"/> instance</param>
+ public PieItem( double pieValue, string label )
+ :
+ this( pieValue, _rotator.NextColor, Default.Displacement, label )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="PieItem"/> object from which to copy</param>
+ public PieItem( PieItem rhs )
+ : base( rhs )
+ {
+ _pieValue = rhs._pieValue;
+ _fill = rhs._fill.Clone();
+ this.Border = rhs._border.Clone();
+ _displacement = rhs._displacement;
+ _labelDetail = rhs._labelDetail.Clone();
+ _labelType = rhs._labelType;
+ _valueDecimalDigits = rhs._valueDecimalDigits;
+ _percentDecimalDigits = rhs._percentDecimalDigits;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public PieItem Clone()
+ {
+ return new PieItem( this );
+ }
+
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PieItem( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _displacement = info.GetDouble( "displacement" );
+ _labelDetail = (TextObj)info.GetValue( "labelDetail", typeof( TextObj ) );
+ _fill = (Fill)info.GetValue( "fill", typeof( Fill ) );
+ _border = (Border)info.GetValue( "border", typeof( Border ) );
+ _pieValue = info.GetDouble( "pieValue" );
+ _labelType = (PieLabelType)info.GetValue( "labelType", typeof( PieLabelType ) );
+ _intersectionPoint = (PointF)info.GetValue( "intersectionPoint", typeof( PointF ) );
+ _boundingRectangle = (RectangleF)info.GetValue( "boundingRectangle", typeof( RectangleF ) );
+ _pivotPoint = (PointF)info.GetValue( "pivotPoint", typeof( PointF ) );
+ _endPoint = (PointF)info.GetValue( "endPoint", typeof( PointF ) );
+ // _slicePath = (GraphicsPath)info.GetValue( "slicePath", typeof( GraphicsPath ) );
+ _startAngle = (float)info.GetDouble( "startAngle" );
+ _sweepAngle = (float)info.GetDouble( "sweepAngle" );
+ _midAngle = (float)info.GetDouble( "midAngle" );
+ _labelStr = info.GetString( "labelStr" );
+ _valueDecimalDigits = info.GetInt32( "valueDecimalDigits" );
+ _percentDecimalDigits = info.GetInt32( "percentDecimalDigits" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "displacement", _displacement );
+ info.AddValue( "labelDetail", _labelDetail );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "pieValue", _pieValue );
+ info.AddValue( "labelType", _labelType );
+ info.AddValue( "intersectionPoint", _intersectionPoint );
+ info.AddValue( "boundingRectangle", _boundingRectangle );
+ info.AddValue( "pivotPoint", _pivotPoint );
+ info.AddValue( "endPoint", _endPoint );
+ // info.AddValue( "slicePath", _slicePath );
+ info.AddValue( "startAngle", _startAngle );
+ info.AddValue( "sweepAngle", _sweepAngle );
+ info.AddValue( "midAngle", _midAngle );
+ info.AddValue( "labelStr", _labelStr );
+ info.AddValue( "valueDecimalDigits", _valueDecimalDigits );
+ info.AddValue( "percentDecimalDigits", _percentDecimalDigits );
+ }
+
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Do all rendering associated with this <see cref="PieItem"/> item to the specified
+ /// <see cref="Graphics"/> device. This method is normally only
+ /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
+ /// collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="pos">Not used for rendering Pies</param>param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor )
+ {
+ if ( pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0 )
+ {
+ //pane.PieRect = RectangleF.Empty;
+ _slicePath = null;
+ }
+ else
+ {
+ //pane.PieRect = CalcPieRect( g, pane, scaleFactor, pane.ChartRect );
+ CalcPieRect( g, pane, scaleFactor, pane.Chart._rect );
+
+ _slicePath = new GraphicsPath();
+
+ if ( !_isVisible )
+ return;
+
+ RectangleF tRect = _boundingRectangle;
+
+ if ( tRect.Width >= 1 && tRect.Height >= 1 )
+ {
+ SmoothingMode sMode = g.SmoothingMode;
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+
+ Fill tFill = _fill;
+ Border tBorder = _border;
+ if ( this.IsSelected )
+ {
+ tFill = Selection.Fill;
+ tBorder = Selection.Border;
+ }
+
+ using ( Brush brush = tFill.MakeBrush( _boundingRectangle ) )
+ {
+ g.FillPie( brush, tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle );
+
+ //add GraphicsPath for hit testing
+ _slicePath.AddPie( tRect.X, tRect.Y, tRect.Width, tRect.Height,
+ this.StartAngle, this.SweepAngle );
+
+ if ( this.Border.IsVisible )
+ {
+ using ( Pen borderPen = tBorder.GetPen( pane, scaleFactor ) )
+ {
+ g.DrawPie( borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height,
+ this.StartAngle, this.SweepAngle );
+ }
+ }
+
+ if ( _labelType != PieLabelType.None )
+ DrawLabel( g, pane, tRect, scaleFactor );
+
+ //brush.Dispose();
+ }
+
+ g.SmoothingMode = sMode;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculate the <see cref="RectangleF"/> that will be used to define the bounding rectangle of
+ /// the Pie.
+ /// </summary>
+ /// <remarks>This rectangle always lies inside of the <see cref="Chart.Rect"/>, and it is
+ /// normally a square so that the pie itself is not oval-shaped.</remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="chartRect">The <see cref="RectangleF"/> (normally the <see cref="Chart.Rect"/>)
+ /// that bounds this pie.</param>
+ /// <returns></returns>
+ public static RectangleF CalcPieRect( Graphics g, GraphPane pane, float scaleFactor, RectangleF chartRect )
+ {
+ //want to draw the largest pie possible within ChartRect
+ //but want to leave 5% slack around the pie so labels will not overrun clip area
+ //largest pie is limited by the smaller of ChartRect.height or ChartRect.width...
+ //this rect (nonExplRect)has to be re-positioned so that it's in the center of ChartRect.
+ //Where ChartRect is almost a square - low Aspect Ratio -, need to contract pieRect so that there's some
+ //room for labels, if they're visible.
+ double maxDisplacement = 0;
+ RectangleF tempRect; //= new RectangleF(0,0,0,0);
+
+ RectangleF nonExplRect = chartRect;
+
+ if ( pane.CurveList.IsPieOnly )
+ {
+ if ( nonExplRect.Width < nonExplRect.Height )
+ {
+ //create slack rect
+ nonExplRect.Inflate( -(float)0.05F * nonExplRect.Height, -(float)0.05F * nonExplRect.Width );
+ //get the difference between dimensions
+ float delta = ( nonExplRect.Height - nonExplRect.Width ) / 2;
+ //make a square so we end up with circular pie
+ nonExplRect.Height = nonExplRect.Width;
+ //keep the center point the same
+ nonExplRect.Y += delta;
+ }
+ else
+ {
+ nonExplRect.Inflate( -(float)0.05F * nonExplRect.Height, -(float)0.05F * nonExplRect.Width );
+ float delta = ( nonExplRect.Width - nonExplRect.Height ) / 2;
+ nonExplRect.Width = nonExplRect.Height;
+ nonExplRect.X += delta;
+ }
+ //check aspect ratio
+ double aspectRatio = chartRect.Width / chartRect.Height;
+ //make an adjustment in rect size,as aspect ratio varies
+ if ( aspectRatio < 1.5 )
+ nonExplRect.Inflate( -(float)( .1 * ( 1.5 / aspectRatio ) * nonExplRect.Width ),
+ -(float)( .1 * ( 1.5 / aspectRatio ) * nonExplRect.Width ) );
+
+ //modify the rect to determine if any of the labels need to be wrapped....
+ //first see if there's any exploded slices and if so, what's the max displacement...
+ //also, might as well get all the display params we can
+ PieItem.CalculatePieChartParams( pane, ref maxDisplacement );
+
+ if ( maxDisplacement != 0 ) //need new rectangle if any slice exploded
+ CalcNewBaseRect( maxDisplacement, ref nonExplRect );
+
+ foreach ( PieItem slice in pane.CurveList )
+ {
+ slice._boundingRectangle = nonExplRect;
+ //if exploded, need to re-calculate rectangle for slice
+ if ( slice.Displacement != 0 )
+ {
+ tempRect = nonExplRect;
+ slice.CalcExplodedRect( ref tempRect );
+ slice._boundingRectangle = tempRect;
+ }
+ //now get all the other slice specific drawing details, including need for wrapping label
+ slice.DesignLabel( g, pane, slice._boundingRectangle, scaleFactor );
+ }
+ }
+ return nonExplRect;
+ }
+
+ /// <summary>
+ /// Recalculate the bounding rectangle when a piee slice is displaced.
+ /// </summary>
+ /// <param name="explRect">rectangle to be used for drawing exploded pie</param>
+ private void CalcExplodedRect( ref RectangleF explRect )
+ {
+ //pie exploded out along the slice bisector - modify upper left of bounding rect to account for displacement
+ //keep height and width same
+ explRect.X += (float)( this.Displacement * explRect.Width / 2 * Math.Cos( _midAngle * Math.PI / 180 ) );
+ explRect.Y += (float)( this.Displacement * explRect.Height / 2 * Math.Sin( _midAngle * Math.PI / 180 ) );
+ }
+
+ /// <summary>
+ /// Calculate the values needed to properly display this <see cref="PieItem"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="maxDisplacement">maximum slice displacement</param>
+ private static void CalculatePieChartParams( GraphPane pane, ref double maxDisplacement )
+ {
+ string lblStr = " ";
+
+ //loop thru slices and get total value and maxDisplacement
+ double pieTotalValue = 0;
+ foreach ( PieItem curve in pane.CurveList )
+ if ( curve.IsPie )
+ {
+ pieTotalValue += curve._pieValue;
+ if ( curve.Displacement > maxDisplacement )
+ maxDisplacement = curve.Displacement;
+ }
+
+ double nextStartAngle = 0;
+ //now loop thru and calculate the various angle values
+ foreach ( PieItem curve in pane.CurveList )
+ {
+ lblStr = curve._labelStr;
+ curve.StartAngle = (float)nextStartAngle;
+ curve.SweepAngle = (float)( 360 * curve.Value / pieTotalValue );
+ curve.MidAngle = curve.StartAngle + curve.SweepAngle / 2;
+ nextStartAngle = curve._startAngle + curve._sweepAngle;
+ PieItem.BuildLabelString( curve );
+ }
+ }
+
+ /// <summary>
+ /// Render the label for this <see cref="PieItem"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">Bounding rectangle for this <see cref="PieItem"/>.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DrawLabel( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ if ( !_labelDetail.IsVisible )
+ return;
+
+ using ( Pen labelPen = this.Border.GetPen( pane, scaleFactor ) )
+ {
+ //draw line from intersection point to pivot point -
+ g.DrawLine( labelPen, _intersectionPoint, _pivotPoint );
+
+ //draw horizontal line to move label away from pie...
+ g.DrawLine( labelPen, _pivotPoint, _endPoint );
+ }
+
+ //draw the label (TextObj)
+ _labelDetail.Draw( g, pane, scaleFactor );
+ }
+
+ /// <summary>
+ /// This method collects all the data relative to rendering this <see cref="PieItem"/>'s label.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="rect">The rectangle used for rendering this <see cref="PieItem"/>
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public void DesignLabel( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ if ( !_labelDetail.IsVisible )
+ return;
+
+ _labelDetail.LayoutArea = new SizeF();
+ //this.labelDetail.IsWrapped = false;
+
+ //label line will come off the explosion radius and then pivot to the horizontal right or left,
+ //dependent on position..
+ //text will be at the end of horizontal segment...
+ CalculateLinePoints( rect, _midAngle );
+
+ //now get size of bounding rect for label
+ SizeF size = _labelDetail.FontSpec.BoundingBox( g, _labelStr, scaleFactor );
+
+ //how much room left for the label - most likely midangles for wrapping
+ //Right - 315 -> 45 degrees
+ //Bottom - 45 -> 135
+ //Left - 135 -> 225
+ //Top - 225 -> 315
+ RectangleF chartRect = pane.Chart._rect;
+ float fill = 0;
+ if ( _midAngle > 315 || _midAngle <= 45 )
+ {
+ //correct by wrapping text
+ fill = chartRect.X + chartRect.Width - _endPoint.X - 5;
+ if ( size.Width > fill )
+ {
+ //need to wrap, so create label rectangle for overloaded DrawString - two rows, max
+ _labelDetail.LayoutArea = new SizeF( fill, size.Height * 3.0F );
+ }
+ }
+
+ if ( _midAngle > 45 && _midAngle <= 135 )
+ {
+ //correct by moving radial line toward one or the other end of the range
+ fill = chartRect.Y + chartRect.Height - _endPoint.Y - 5;
+ //is there enuf room for the label
+ if ( size.Height / 2 > fill )
+ {
+ //no, so got to move explosion radius
+ if ( _midAngle > 90 ) //move _label clockwise one-third of way to the end of the arc
+ CalculateLinePoints( rect, _midAngle + ( _sweepAngle + _startAngle - _midAngle ) / 3 );
+ else //move _label counter-clockwise one-third of way to the start of the arc
+ CalculateLinePoints( rect, _midAngle - ( _midAngle - ( _midAngle - _startAngle ) / 3 ) );
+ }
+ }
+
+ if ( _midAngle > 135 && _midAngle <= 225 )
+ {
+ //wrap text
+ fill = _endPoint.X - chartRect.X - 5;
+ //need to wrap, so create label rectangle for overloaded DrawString - two rows, max
+ if ( size.Width > fill )
+ {
+ _labelDetail.LayoutArea = new SizeF( fill, size.Height * 3.0F );
+ }
+ }
+
+ if ( _midAngle > 225 && _midAngle <= 315 )
+ {
+ //correct by moving radial line toward one or the other end of the range
+ fill = _endPoint.Y - 5 - chartRect.Y;
+ //is there enuf room for the label
+ if ( size.Height / 2 > fill )
+ {
+ //no, so got to move explosion radius
+ if ( _midAngle < 270 ) //move _label counter-clockwise one-third of way to the start of the arc
+ CalculateLinePoints( rect, _midAngle - ( _sweepAngle + _startAngle - _midAngle ) / 3 );
+ else //move _label clockwise one-third of way to the end of the arc
+ CalculateLinePoints( rect, _midAngle + ( _midAngle - _startAngle ) / 3 );
+ }
+ }
+
+ //complete the location Detail info
+ _labelDetail.Location.AlignV = AlignV.Center;
+ _labelDetail.Location.CoordinateFrame = CoordType.PaneFraction;
+ _labelDetail.Location.X = ( _endPoint.X - pane.Rect.X ) / pane.Rect.Width;
+ _labelDetail.Location.Y = ( _endPoint.Y - pane.Rect.Y ) / pane.Rect.Height;
+ _labelDetail.Text = _labelStr;
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="rect"></param>
+ /// <param name="midAngle"></param>
+ private void CalculateLinePoints( RectangleF rect, double midAngle )
+ {
+ //get the point where the explosion radius intersects the this arc
+ PointF rectCenter = new PointF( ( rect.X + rect.Width / 2 ), ( rect.Y + rect.Height / 2 ) );
+
+ _intersectionPoint = new PointF( (float)( rectCenter.X + ( rect.Width / 2 * Math.Cos( ( midAngle ) * Math.PI / 180 ) ) ),
+ (float)( rectCenter.Y + ( rect.Height / 2 * Math.Sin( ( midAngle ) * Math.PI / 180 ) ) ) );
+
+ //draw line from intersection point to pivot point - length to be .05 * pieRect.Width pixels long
+ _pivotPoint = new PointF( (float)( _intersectionPoint.X + .05 * rect.Width * Math.Cos( ( midAngle ) * Math.PI / 180 ) ),
+ (float)( _intersectionPoint.Y + .05 * rect.Width * Math.Sin( ( midAngle ) * Math.PI / 180 ) ) );
+
+ //add horizontal line to move label away from pie...length to be 5% of rect.Width
+ //does line go to left or right....label alignment is to the opposite
+ if ( _pivotPoint.X >= rectCenter.X ) //goes to right
+ {
+ _endPoint = new PointF( (float)( _pivotPoint.X + .05 * rect.Width ), _pivotPoint.Y );
+ _labelDetail.Location.AlignH = AlignH.Left;
+ }
+ else
+ {
+ _endPoint = new PointF( (float)( _pivotPoint.X - .05 * rect.Width ), _pivotPoint.Y );
+ _labelDetail.Location.AlignH = AlignH.Right;
+ }
+ _midAngle = (float)midAngle;
+ }
+
+ /// <summary>
+ /// Build the string that will be displayed as the slice label as determined by
+ /// <see cref="LabelType"/>.
+ /// </summary>
+ /// <param name="curve">reference to the <see cref="PieItem"/></param>
+ private static void BuildLabelString( PieItem curve )
+ {
+ //set up label string formatting
+ NumberFormatInfo labelFormat = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone();
+
+ labelFormat.NumberDecimalDigits = curve._valueDecimalDigits;
+ labelFormat.PercentPositivePattern = 1; //no space between number and % sign
+ labelFormat.PercentDecimalDigits = curve._percentDecimalDigits;
+
+ switch ( curve._labelType )
+ {
+ case PieLabelType.Value:
+ curve._labelStr = curve._pieValue.ToString( "F", labelFormat );
+ break;
+ case PieLabelType.Percent:
+ curve._labelStr = ( curve._sweepAngle / 360 ).ToString( "P", labelFormat );
+ break;
+ case PieLabelType.Name_Value:
+ curve._labelStr = curve._label._text + ": " + curve._pieValue.ToString( "F", labelFormat );
+ break;
+ case PieLabelType.Name_Percent:
+ curve._labelStr = curve._label._text + ": " + ( curve._sweepAngle / 360 ).ToString( "P", labelFormat );
+ break;
+ case PieLabelType.Name_Value_Percent:
+ curve._labelStr = curve._label._text + ": " + curve._pieValue.ToString( "F", labelFormat ) +
+ " (" + ( curve._sweepAngle / 360 ).ToString( "P", labelFormat ) + ")";
+ break;
+ case PieLabelType.Name:
+ curve._labelStr = curve._label._text;
+ break;
+ case PieLabelType.None:
+ default:
+ break;
+ }
+ }
+
+ /// <summary>
+ /// A method which calculates a new size for the bounding rectangle for the non-displaced
+ /// <see cref="PieItem"/>'s in the pie chart. This method is called after it is found
+ /// that at least one slice is displaced.
+ /// </summary>
+ /// <param name="maxDisplacement">The biggest displacement among the <see cref="PieItem"/>s
+ /// making up the pie chart.</param>
+ /// <param name="baseRect">The current bounding rectangle</param>
+ private static void CalcNewBaseRect( double maxDisplacement, ref RectangleF baseRect )
+ {
+ //displacement expressed in terms of % of pie radius ...do not want exploded slice to
+ //go beyond nonExplRect, but want to maintain the same center point...therefore, got to
+ //reduce the diameter of the nonexploded pie by the alue of the displacement
+
+ float xDispl = (float)( ( maxDisplacement * baseRect.Width ) );
+ float yDispl = (float)( ( maxDisplacement * baseRect.Height ) );
+
+ baseRect.Inflate( -(float)( ( xDispl / 10 ) ), -(float)( ( xDispl / 10 ) ) );
+ }
+
+ /// <summary>
+ /// Draw a legend key entry for this <see cref="PieItem"/> at the specified location
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
+ /// location for the legend key</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor )
+ {
+ if ( !_isVisible )
+ return;
+
+ // Fill the slice
+ if ( _fill.IsVisible )
+ {
+ // just avoid height/width being less than 0.1 so GDI+ doesn't cry
+ using ( Brush brush = _fill.MakeBrush( rect ) )
+ {
+ g.FillRectangle( brush, rect );
+ //brush.Dispose();
+ }
+ }
+
+ // Border the bar
+ if ( !_border.Color.IsEmpty )
+ _border.Draw( g, pane, scaleFactor, rect );
+ }
+
+ /// <summary>
+ /// Determine the coords for the rectangle associated with a specified point for
+ /// this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
+ /// <param name="i">The index of the point of interest</param>
+ /// <param name="coords">A list of coordinates that represents the "rect" for
+ /// this point (used in an html AREA tag)</param>
+ /// <returns>true if it's a valid point, false otherwise</returns>
+ override public bool GetCoords( GraphPane pane, int i, out string coords )
+ {
+ coords = string.Empty;
+
+ PointF pt = _boundingRectangle.Location;
+ pt.X += _boundingRectangle.Width / 2.0f;
+ pt.Y += _boundingRectangle.Height / 2.0f;
+
+ float radius = _boundingRectangle.Width / 2.0f;
+ Matrix matrix = new Matrix();
+
+ // Move the coordinate system to local coordinates
+ // of this text object (that is, at the specified
+ // x,y location)
+ matrix.Translate( pt.X, pt.Y );
+
+ matrix.Rotate( this.StartAngle );
+ //One mark every 5'ish degrees
+ int count = (int)Math.Floor ( SweepAngle / 5 ) + 1;
+ PointF[] pts = new PointF[2 + count];
+ pts[0] = new PointF( 0, 0 );
+ pts[1] = new PointF( radius, 0 );
+ double angle = 0.0;
+ for ( int j = 2; j < count + 2; j++ )
+ {
+ angle += SweepAngle / count;
+
+ pts[j] = new PointF(radius * (float)Math.Cos(angle * Math.PI / 180.0),
+ radius * (float)Math.Sin( angle * Math.PI / 180.0 ) );
+ }
+
+ matrix.TransformPoints( pts );
+
+ coords = String.Format("{0:f0},{1:f0},{2:f0},{3:f0},",
+ pts[0].X, pts[0].Y, pts[1].X, pts[1].Y );
+ for (int j = 2; j < count + 2; j++)
+ coords += String.Format(j > count ? "{0:f0},{1:f0}" : "{0:f0},{1:f0},", pts[j].X, pts[j].Y);
+
+ return true;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PointD.cs b/ZedGraph/PointD.cs
new file mode 100644
index 0000000..71715a2
--- /dev/null
+++ b/ZedGraph/PointD.cs
@@ -0,0 +1,59 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Simple struct that stores X and Y coordinates as doubles.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ [Serializable]
+ public struct PointD
+ {
+ /// <summary>
+ /// The X coordinate
+ /// </summary>
+ public double X;
+ /// <summary>
+ /// The Y coordinate
+ /// </summary>
+ public double Y;
+
+ /// <summary>
+ /// Construct a <see cref="PointD" /> object from two double values.
+ /// </summary>
+ /// <param name="x">The X coordinate</param>
+ /// <param name="y">The Y coordinate</param>
+ public PointD( double x, double y )
+ {
+ X = x;
+ Y = y;
+ }
+ }
+}
+
diff --git a/ZedGraph/PointPair.cs b/ZedGraph/PointPair.cs
new file mode 100644
index 0000000..441d27e
--- /dev/null
+++ b/ZedGraph/PointPair.cs
@@ -0,0 +1,561 @@
+//============================================================================
+//PointPair Class
+//Copyright � 2004 Jerry Vos
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Collections;
+using IComparer = System.Collections.IComparer;
+
+#if ( !DOTNET1 ) // Is this a .Net 2 compilation?
+using System.Collections.Generic;
+#endif
+
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A simple point represented by an (X,Y,Z) group of double values.
+ /// </summary>
+ ///
+ /// <author> Jerry Vos modified by John Champion </author>
+ /// <version> $Revision: 3.26 $ $Date: 2007-11-28 02:38:22 $ </version>
+ [Serializable]
+ public class PointPair : PointPairBase, ISerializable, ICloneable
+ {
+ #region Member variables
+
+ /// <summary>
+ /// This PointPair's Z coordinate. Also used for the lower value (dependent axis)
+ /// for <see cref="HiLowBarItem"/> and <see cref="ErrorBarItem" /> charts.
+ /// </summary>
+ public double Z;
+
+ /// <summary>
+ /// A tag object for use by the user. This can be used to store additional
+ /// information associated with the <see cref="PointPair"/>. ZedGraph never
+ /// modifies this value, but if it is a <see cref="String"/> type, it
+ /// may be displayed in a <see cref="System.Windows.Forms.ToolTip"/>
+ /// within the <see cref="ZedGraphControl"/> object.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if you are going to Serialize ZedGraph data, then any type
+ /// that you store in <see cref="Tag"/> must be a serializable type (or
+ /// it will cause an exception).
+ /// </remarks>
+ public object Tag;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public PointPair() : this( 0, 0, 0, null )
+ {
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X and Y.
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ public PointPair( double x, double y )
+ : this ( x, y, 0, null )
+ {
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, and
+ /// label (<see cref="Tag"/>).
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="label">This pair's string label (<see cref="Tag"/>)</param>
+ public PointPair( double x, double y, string label )
+ : this( x, y, 0, label as object )
+ {
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, and base value.
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="z">This pair's z or lower dependent coordinate.</param>
+ public PointPair( double x, double y, double z )
+ : this( x, y, z, null )
+ {
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, base value, and
+ /// string label (<see cref="Tag"/>).
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="z">This pair's z or lower dependent coordinate.</param>
+ /// <param name="label">This pair's string label (<see cref="Tag"/>)</param>
+ public PointPair( double x, double y, double z, string label )
+ : this( x, y, z, label as object )
+ {
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, base value, and
+ /// (<see cref="Tag"/>).
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="z">This pair's z or lower dependent coordinate.</param>
+ /// <param name="tag">This pair's <see cref="Tag"/> property</param>
+ public PointPair( double x, double y, double z, object tag )
+ : base( x, y )
+ {
+ this.Z = z;
+ this.Tag = tag;
+ }
+
+ /// <summary>
+ /// Creates a point pair from the specified <see cref="PointF"/> struct.
+ /// </summary>
+ /// <param name="pt">The <see cref="PointF"/> struct from which to get the
+ /// new <see cref="PointPair"/> values.</param>
+ public PointPair( PointF pt ) : this( pt.X, pt.Y, 0, null )
+ {
+ }
+
+ /// <summary>
+ /// The PointPair copy constructor.
+ /// </summary>
+ /// <param name="rhs">The basis for the copy.</param>
+ public PointPair( PointPair rhs ) : base( rhs )
+ {
+ this.Z = rhs.Z;
+
+ if ( rhs.Tag is ICloneable )
+ this.Tag = ((ICloneable) rhs.Tag).Clone();
+ else
+ this.Tag = rhs.Tag;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public PointPair Clone()
+ {
+ return new PointPair( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PointPair( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ Z = info.GetDouble( "Z" );
+ Tag = info.GetValue( "Tag", typeof(object) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "Z", Z );
+ info.AddValue( "Tag", Tag );
+ }
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Readonly value that determines if either the X, Y, or Z
+ /// coordinate in this PointPair is an invalid (not plotable) value.
+ /// It is considered invalid if it is missing (equal to System.Double.Max),
+ /// Infinity, or NaN.
+ /// </summary>
+ /// <returns>true if any value is invalid</returns>
+ public bool IsInvalid3D
+ {
+ get { return this.X == PointPair.Missing ||
+ this.Y == PointPair.Missing ||
+ this.Z == PointPair.Missing ||
+ Double.IsInfinity( this.X ) ||
+ Double.IsInfinity( this.Y ) ||
+ Double.IsInfinity( this.Z ) ||
+ Double.IsNaN( this.X ) ||
+ Double.IsNaN( this.Y ) ||
+ Double.IsNaN( this.Z );
+ }
+ }
+
+ /// <summary>
+ /// The "low" value for this point (lower dependent-axis value).
+ /// This is really just an alias for <see cref="PointPair.Z"/>.
+ /// </summary>
+ /// <value>The lower dependent value for this <see cref="PointPair"/>.</value>
+ public double LowValue
+ {
+ get { return this.Z; }
+ set { this.Z = value; }
+ }
+
+ /// <summary>
+ /// The ColorValue property is just an alias for the <see cref="PointPair.Z" />
+ /// property.
+ /// </summary>
+ /// <remarks>
+ /// For other types, such as the <see cref="StockPt"/>, the <see cref="StockPt" />
+ /// can be mapped to a unique value. This is used with the
+ /// <see cref="FillType.GradientByColorValue" /> option.
+ /// </remarks>
+ virtual public double ColorValue
+ {
+ get { return Z; }
+ set { Z = value; }
+ }
+
+ #endregion
+
+ #region Inner classes
+
+ #if ( DOTNET1 ) // Is this a .Net 1.1 compilation?
+
+ /// <summary>
+ /// Compares points based on their y values. Is setup to be used in an
+ /// ascending order sort.
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/>
+ /// </summary>
+ public class PointPairComparerY : IComparer
+ {
+
+ /// <summary>
+ /// Compares two <see cref="PointPair"/>s.
+ /// </summary>
+ /// <param name="l">Point to the left.</param>
+ /// <param name="r">Point to the right.</param>
+ /// <returns>-1, 0, or 1 depending on l.Y's relation to r.Y</returns>
+ public int Compare( object l, object r )
+ {
+ PointPair pl = (PointPair) l;
+ PointPair pr = (PointPair) r;
+
+ if (pl == null && pr == null)
+ {
+ return 0;
+ }
+ else if (pl == null && pr != null)
+ {
+ return -1;
+ }
+ else if (pl != null && pr == null)
+ {
+ return 1;
+ }
+
+ double lY = pl.Y;
+ double rY = pr.Y;
+
+ if (System.Math.Abs(lY - rY) < .000000001)
+ return 0;
+
+ return lY < rY ? -1 : 1;
+ }
+ }
+
+ /// <summary>
+ /// Compares points based on their x values. Is setup to be used in an
+ /// ascending order sort.
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/>
+ /// </summary>
+ public class PointPairComparer : IComparer
+ {
+ private SortType sortType;
+
+ /// <summary>
+ /// Constructor for PointPairComparer.
+ /// </summary>
+ /// <param name="type">The axis type on which to sort.</param>
+ public PointPairComparer( SortType type )
+ {
+ this.sortType = type;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="PointPair"/>s.
+ /// </summary>
+ /// <param name="l">Point to the left.</param>
+ /// <param name="r">Point to the right.</param>
+ /// <returns>-1, 0, or 1 depending on l.X's relation to r.X</returns>
+ public int Compare( object l, object r )
+ {
+ PointPair pl = (PointPair) l;
+ PointPair pr = (PointPair) r;
+
+ if ( pl == null && pr == null )
+ return 0;
+ else if ( pl == null && pr != null )
+ return -1;
+ else if ( pl != null && pr == null )
+ return 1;
+
+ double lVal, rVal;
+
+ if ( sortType == SortType.XValues )
+ {
+ lVal = pl.X;
+ rVal = pr.X;
+ }
+ else
+ {
+ lVal = pl.Y;
+ rVal = pr.Y;
+ }
+
+ if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
+ pl = null;
+ if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
+ pr = null;
+
+ if ( ( pl == null && pr == null ) || ( System.Math.Abs( lVal - rVal ) < 1e-10 ) )
+ return 0;
+ else if ( pl == null && pr != null )
+ return -1;
+ else if ( pl != null && pr == null )
+ return 1;
+ else
+ return lVal < rVal ? -1 : 1;
+ }
+ }
+
+ #else // Otherwise, it's .Net 2.0, so use generics
+
+ /// <summary>
+ /// Compares points based on their y values. Is setup to be used in an
+ /// ascending order sort.
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/>
+ /// </summary>
+ public class PointPairComparerY : IComparer<PointPair>
+ {
+
+ /// <summary>
+ /// Compares two <see cref="PointPair"/>s.
+ /// </summary>
+ /// <param name="l">Point to the left.</param>
+ /// <param name="r">Point to the right.</param>
+ /// <returns>-1, 0, or 1 depending on l.Y's relation to r.Y</returns>
+ public int Compare( PointPair? l, PointPair? r )
+ {
+ if ( l == null && r == null )
+ {
+ return 0;
+ }
+ else if ( l == null && r != null )
+ {
+ return -1;
+ }
+ else if ( l != null && r == null )
+ {
+ return 1;
+ }
+
+ double lY = l.Y;
+ double rY = r.Y;
+
+ if ( System.Math.Abs( lY - rY ) < .000000001 )
+ return 0;
+
+ return lY < rY ? -1 : 1;
+ }
+ }
+
+ /// <summary>
+ /// Compares points based on their x values. Is setup to be used in an
+ /// ascending order sort.
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/>
+ /// </summary>
+ public class PointPairComparer : IComparer<PointPair>
+ {
+ private SortType sortType;
+
+ /// <summary>
+ /// Constructor for PointPairComparer.
+ /// </summary>
+ /// <param name="type">The axis type on which to sort.</param>
+ public PointPairComparer( SortType type )
+ {
+ this.sortType = type;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="PointPair"/>s.
+ /// </summary>
+ /// <param name="l">Point to the left.</param>
+ /// <param name="r">Point to the right.</param>
+ /// <returns>-1, 0, or 1 depending on l.X's relation to r.X</returns>
+ public int Compare( PointPair? l, PointPair? r )
+ {
+ if ( l == null && r == null )
+ return 0;
+ else if ( l == null && r != null )
+ return -1;
+ else if ( l != null && r == null )
+ return 1;
+
+ double lVal, rVal;
+
+ if ( sortType == SortType.XValues )
+ {
+ lVal = l.X;
+ rVal = r.X;
+ }
+ else
+ {
+ lVal = l.Y;
+ rVal = r.Y;
+ }
+
+ if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
+ l = null;
+ if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
+ r = null;
+
+ if ( ( l == null && r == null ) || ( System.Math.Abs( lVal - rVal ) < 1e-100 ) )
+ return 0;
+ else if ( l == null && r != null )
+ return -1;
+ else if ( l != null && r == null )
+ return 1;
+ else
+ return lVal < rVal ? -1 : 1;
+ }
+ }
+
+ #endif
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Compare two <see cref="PointPair"/> objects for equality. To be equal, X, Y, and Z
+ /// must be exactly the same between the two objects.
+ /// </summary>
+ /// <param name="obj">The <see cref="PointPair"/> object to be compared with.</param>
+ /// <returns>true if the <see cref="PointPair"/> objects are equal, false otherwise</returns>
+ public override bool Equals( object obj )
+ {
+ PointPair rhs = obj as PointPair;
+ return this.X == rhs.X && this.Y == rhs.Y && this.Z == rhs.Z;
+ }
+
+ /// <summary>
+ /// Return the HashCode from the base class.
+ /// </summary>
+ /// <returns></returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Format this PointPair value using the default format. Example: "( 12.345, -16.876 )".
+ /// The two double values are formatted with the "g" format type.
+ /// </summary>
+ /// <param name="isShowZ">true to show the third "Z" or low dependent value coordinate</param>
+ /// <returns>A string representation of the PointPair</returns>
+ virtual public string ToString( bool isShowZ )
+ {
+ return this.ToString( PointPair.DefaultFormat, isShowZ );
+ }
+
+ /// <summary>
+ /// Format this PointPair value using a general format string.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// If <see paramref="isShowZ"/>
+ /// is true, then the third "Z" coordinate is also shown.
+ /// </summary>
+ /// <param name="format">A format string that will be used to format each of
+ /// the two double type values (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ /// <param name="isShowZ">true to show the third "Z" or low dependent value coordinate</param>
+ virtual public string ToString( string format, bool isShowZ )
+ {
+ return "( " + this.X.ToString( format ) +
+ ", " + this.Y.ToString( format ) +
+ ( isShowZ ? ( ", " + this.Z.ToString( format ) ) : "" )
+ + " )";
+ }
+
+ /// <summary>
+ /// Format this PointPair value using different general format strings for the X, Y, and Z values.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// </summary>
+ /// <param name="formatX">A format string that will be used to format the X
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <param name="formatY">A format string that will be used to format the Y
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <param name="formatZ">A format string that will be used to format the Z
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ public string ToString( string formatX, string formatY, string formatZ )
+ {
+ return "( " + this.X.ToString( formatX ) +
+ ", " + this.Y.ToString( formatY ) +
+ ", " + this.Z.ToString( formatZ ) +
+ " )";
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PointPair4.cs b/ZedGraph/PointPair4.cs
new file mode 100644
index 0000000..fecc579
--- /dev/null
+++ b/ZedGraph/PointPair4.cs
@@ -0,0 +1,217 @@
+//============================================================================
+//PointPair4 Class
+//Copyright � 2006 Jerry Vos & John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using IComparer = System.Collections.IComparer;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The basic <see cref="PointPair" /> class holds three data values (X, Y, Z). This
+ /// class extends the basic PointPair to contain four data values (X, Y, Z, T).
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.3 $ $Date: 2007-03-17 18:43:44 $ </version>
+ [Serializable]
+ public class PointPair4 : PointPair, ISerializable
+ {
+
+ #region Member variables
+
+ /// <summary>
+ /// This PointPair4's T coordinate.
+ /// </summary>
+ public double T;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public PointPair4() : base()
+ {
+ this.T = 0;
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, Z, and T value.
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="z">This pair's z coordinate.</param>
+ /// <param name="t">This pair's t coordinate.</param>
+ public PointPair4( double x, double y, double z, double t ) : base( x, y, z )
+ {
+ this.T = t;
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, base value, and
+ /// label (<see cref="PointPair.Tag"/>).
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="z">This pair's z coordinate.</param>
+ /// <param name="t">This pair's t coordinate.</param>
+ /// <param name="label">This pair's string label (<see cref="PointPair.Tag"/>)</param>
+ public PointPair4( double x, double y, double z, double t, string label ) :
+ base( x, y, z, label )
+ {
+ this.T = t;
+ }
+
+ /// <summary>
+ /// The PointPair4 copy constructor.
+ /// </summary>
+ /// <param name="rhs">The basis for the copy.</param>
+ public PointPair4( PointPair4 rhs ) : base( rhs )
+ {
+ this.T = rhs.T;
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PointPair4( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+
+ T = info.GetDouble( "T" );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema3 );
+ info.AddValue( "T", T );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Readonly value that determines if either the X, Y, Z, or T
+ /// coordinate in this PointPair4 is an invalid (not plotable) value.
+ /// It is considered invalid if it is missing (equal to System.Double.Max),
+ /// Infinity, or NaN.
+ /// </summary>
+ /// <returns>true if any value is invalid</returns>
+ public bool IsInvalid4D
+ {
+ get
+ {
+ return this.X == PointPair.Missing ||
+ this.Y == PointPair.Missing ||
+ this.Z == PointPair.Missing ||
+ this.T == PointPair.Missing ||
+ Double.IsInfinity( this.X ) ||
+ Double.IsInfinity( this.Y ) ||
+ Double.IsInfinity( this.Z ) ||
+ Double.IsInfinity( this.T ) ||
+ Double.IsNaN( this.X ) ||
+ Double.IsNaN( this.Y ) ||
+ Double.IsNaN( this.Z ) ||
+ Double.IsNaN( this.T );
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Format this PointPair4 value using the default format. Example: "( 12.345, -16.876 )".
+ /// The two double values are formatted with the "g" format type.
+ /// </summary>
+ /// <param name="isShowZT">true to show the third "Z" and fourth "T" value coordinates</param>
+ /// <returns>A string representation of the PointPair4</returns>
+ public new string ToString( bool isShowZT )
+ {
+ return this.ToString( PointPair.DefaultFormat, isShowZT );
+ }
+
+ /// <summary>
+ /// Format this PointPair value using a general format string.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// If <see paramref="isShowZ"/>
+ /// is true, then the third "Z" coordinate is also shown.
+ /// </summary>
+ /// <param name="format">A format string that will be used to format each of
+ /// the two double type values (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ /// <param name="isShowZT">true to show the third "Z" or low dependent value coordinate</param>
+ public new string ToString( string format, bool isShowZT )
+ {
+ return "( " + this.X.ToString( format ) +
+ ", " + this.Y.ToString( format ) +
+ ( isShowZT ? ( ", " + this.Z.ToString( format ) +
+ ", " + this.T.ToString( format ) ): "" ) + " )";
+ }
+
+ /// <summary>
+ /// Format this PointPair value using different general format strings for the X, Y, and Z values.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// </summary>
+ /// <param name="formatX">A format string that will be used to format the X
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <param name="formatY">A format string that will be used to format the Y
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <param name="formatZ">A format string that will be used to format the Z
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <param name="formatT">A format string that will be used to format the T
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ public string ToString( string formatX, string formatY, string formatZ, string formatT )
+ {
+ return "( " + this.X.ToString( formatX ) +
+ ", " + this.Y.ToString( formatY ) +
+ ", " + this.Z.ToString( formatZ ) +
+ ", " + this.T.ToString( formatT ) +
+ " )";
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/PointPairBase.cs b/ZedGraph/PointPairBase.cs
new file mode 100644
index 0000000..8a585fe
--- /dev/null
+++ b/ZedGraph/PointPairBase.cs
@@ -0,0 +1,280 @@
+//============================================================================
+//PointPairBase Class
+//Copyright � 2006 Jerry Vos & John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using IComparer = System.Collections.IComparer;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This is a base class that provides base-level functionality for a data point consisting
+ /// of an (X,Y) pair of double values.
+ /// </summary>
+ /// <remarks>
+ /// This class is typically a base class for actual <see cref="PointPair" /> type implementations.
+ /// </remarks>
+ ///
+ /// <author> Jerry Vos modified by John Champion </author>
+ /// <version> $Revision: 1.4 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ public class PointPairBase : ISerializable
+ {
+
+ #region Member variables
+
+ /// <summary>
+ /// Missing values are represented internally using <see cref="System.Double.MaxValue"/>.
+ /// </summary>
+ public const double Missing = Double.MaxValue;
+
+ /// <summary>
+ /// The default format to be used for displaying point values via the
+ /// <see cref="ToString()"/> method.
+ /// </summary>
+ public const string DefaultFormat = "G";
+
+ /// <summary>
+ /// This PointPair's X coordinate
+ /// </summary>
+ public double X;
+
+ /// <summary>
+ /// This PointPair's Y coordinate
+ /// </summary>
+ public double Y;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public PointPairBase()
+ : this( 0, 0 )
+ {
+ }
+
+ /// <summary>
+ /// Creates a point pair with the specified X and Y.
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ public PointPairBase( double x, double y )
+ {
+ this.X = x;
+ this.Y = y;
+ }
+
+ /// <summary>
+ /// Creates a point pair from the specified <see cref="PointF"/> struct.
+ /// </summary>
+ /// <param name="pt">The <see cref="PointF"/> struct from which to get the
+ /// new <see cref="PointPair"/> values.</param>
+ public PointPairBase( PointF pt )
+ : this( pt.X, pt.Y )
+ {
+ }
+
+ /// <summary>
+ /// The PointPairBase copy constructor.
+ /// </summary>
+ /// <param name="rhs">The basis for the copy.</param>
+ public PointPairBase( PointPairBase rhs )
+ {
+ this.X = rhs.X;
+ this.Y = rhs.Y;
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PointPairBase( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ X = info.GetDouble( "X" );
+ Y = info.GetDouble( "Y" );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "X", X );
+ info.AddValue( "Y", Y );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Readonly value that determines if either the X or the Y
+ /// coordinate in this PointPair is a missing value.
+ /// </summary>
+ /// <returns>true if either value is missing</returns>
+ public bool IsMissing
+ {
+ get { return this.X == PointPairBase.Missing || this.Y == PointPairBase.Missing; }
+ }
+
+ /// <summary>
+ /// Readonly value that determines if either the X or the Y
+ /// coordinate in this PointPair is an invalid (not plotable) value.
+ /// It is considered invalid if it is missing (equal to System.Double.Max),
+ /// Infinity, or NaN.
+ /// </summary>
+ /// <returns>true if either value is invalid</returns>
+ public bool IsInvalid
+ {
+ get
+ {
+ return this.X == PointPairBase.Missing ||
+ this.Y == PointPairBase.Missing ||
+ Double.IsInfinity( this.X ) ||
+ Double.IsInfinity( this.Y ) ||
+ Double.IsNaN( this.X ) ||
+ Double.IsNaN( this.Y );
+ }
+ }
+
+ /// <summary>
+ /// static method to determine if the specified point value is invalid.
+ /// </summary>
+ /// <remarks>The value is considered invalid if it is <see cref="PointPairBase.Missing"/>,
+ /// <see cref="Double.PositiveInfinity"/>, <see cref="Double.NegativeInfinity"/>
+ /// or <see cref="Double.NaN"/>.</remarks>
+ /// <param name="value">The value to be checked for validity.</param>
+ /// <returns>true if the value is invalid, false otherwise</returns>
+ public static bool IsValueInvalid( double value )
+ {
+ return ( value == PointPairBase.Missing ||
+ Double.IsInfinity( value ) ||
+ Double.IsNaN( value ) );
+ }
+
+ #endregion
+
+ #region Operator Overloads
+
+ /// <summary>
+ /// Implicit conversion from PointPair to PointF. Note that this conversion
+ /// can result in data loss, since the data are being cast from a type
+ /// double (64 bit) to a float (32 bit).
+ /// </summary>
+ /// <param name="pair">The PointPair struct on which to operate</param>
+ /// <returns>A PointF struct equivalent to the PointPair</returns>
+ public static implicit operator PointF( PointPairBase pair )
+ {
+ return new PointF( (float)pair.X, (float)pair.Y );
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Compare two <see cref="PointPairBase"/> objects for equality. To be equal, X and Y
+ /// must be exactly the same between the two objects.
+ /// </summary>
+ /// <param name="obj">The <see cref="PointPairBase"/> object to be compared with.</param>
+ /// <returns>true if the <see cref="PointPairBase"/> objects are equal, false otherwise</returns>
+ public override bool Equals( object? obj )
+ {
+ PointPairBase rhs = obj as PointPairBase;
+ return this.X == rhs.X && this.Y == rhs.Y;
+ }
+
+ /// <summary>
+ /// Return the HashCode from the base class.
+ /// </summary>
+ /// <returns></returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Format this PointPair value using the default format. Example: "( 12.345, -16.876 )".
+ /// The two double values are formatted with the "g" format type.
+ /// </summary>
+ /// <returns>A string representation of the PointPair</returns>
+ public override string ToString()
+ {
+ return this.ToString( PointPairBase.DefaultFormat );
+ }
+
+ /// <summary>
+ /// Format this PointPair value using a general format string.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// </summary>
+ /// <param name="format">A format string that will be used to format each of
+ /// the two double type values (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ public string ToString( string format )
+ {
+ return "( " + this.X.ToString( format ) +
+ ", " + this.Y.ToString( format ) +
+ " )";
+ }
+
+ /// <summary>
+ /// Format this PointPair value using different general format strings for the X and Y values.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// The Z value is not displayed (see <see cref="PointPair.ToString( string, string, string )"/>).
+ /// </summary>
+ /// <param name="formatX">A format string that will be used to format the X
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <param name="formatY">A format string that will be used to format the Y
+ /// double type value (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ public string ToString( string formatX, string formatY )
+ {
+ return "( " + this.X.ToString( formatX ) +
+ ", " + this.Y.ToString( formatY ) +
+ " )";
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PointPairCV.cs b/ZedGraph/PointPairCV.cs
new file mode 100644
index 0000000..a5f1a59
--- /dev/null
+++ b/ZedGraph/PointPairCV.cs
@@ -0,0 +1,121 @@
+//============================================================================
+//PointPairCV Class
+//Copyright � 2007 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#if ( !DOTNET1 ) // Is this a .Net 2 compilation?
+using System.Collections.Generic;
+#endif
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A simple instance that stores a data point (X, Y, Z). This differs from a regular
+ /// <see cref="PointPair" /> in that it maps the <see cref="ColorValue" /> property
+ /// to an independent value. That is, <see cref="ColorValue" /> and
+ /// <see cref="PointPair.Z" /> are not related (as they are in the
+ /// <see cref="PointPair" />).
+ /// </summary>
+ public class PointPairCV : PointPair
+ {
+
+ #region Properties
+
+ /// <summary>
+ /// This is a user value that can be anything. It is used to provide special
+ /// property-based coloration to the graph elements.
+ /// </summary>
+ private double _colorValue;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Creates a point pair with the specified X, Y, and base value.
+ /// </summary>
+ /// <param name="x">This pair's x coordinate.</param>
+ /// <param name="y">This pair's y coordinate.</param>
+ /// <param name="z">This pair's z or lower dependent coordinate.</param>
+ public PointPairCV( double x, double y, double z )
+ : base( x, y, z, null )
+ {
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PointPairCV( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+
+ ColorValue = info.GetDouble( "ColorValue" );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema3", schema2 );
+ info.AddValue( "ColorValue", ColorValue );
+ }
+
+ #endregion
+
+
+ #region Properties
+
+ /// <summary>
+ /// The ColorValue property. This is used with the
+ /// <see cref="FillType.GradientByColorValue" /> option.
+ /// </summary>
+ override public double ColorValue
+ {
+ get { return _colorValue; }
+ set { _colorValue = value; }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/PointPairList.cs b/ZedGraph/PointPairList.cs
new file mode 100644
index 0000000..249dc41
--- /dev/null
+++ b/ZedGraph/PointPairList.cs
@@ -0,0 +1,935 @@
+//============================================================================
+//PointPairList Class
+//Copyright � 2004 Jerry Vos
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="PointPair"/> objects
+ /// that define the set of points to be displayed on the curve.
+ /// </summary>
+ /// <seealso cref="BasicArrayPointList" />
+ /// <seealso cref="IPointList" />
+ ///
+ /// <author> Jerry Vos based on code by John Champion
+ /// modified by John Champion</author>
+ /// <version> $Revision: 3.37 $ $Date: 2007-06-29 15:39:07 $ </version>
+ [Serializable]
+ public class PointPairList : List<PointPair>, IPointList, IPointListEdit
+ {
+ #region Fields
+ /// <summary>Private field to maintain the sort status of this
+ /// <see cref="PointPairList"/>. Use the public property
+ /// <see cref="Sorted"/> to access this value.
+ /// </summary>
+ protected bool _sorted = true;
+ #endregion
+
+ #region Properties
+/* /// <summary>
+ /// Indexer to access the specified <see cref="PointPair"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="PointPair"/> object to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object reference.</value>
+ public PointPair this[ int index ]
+ {
+ get { return (PointPair) List[index]; }
+ set { List[index] = value; }
+ }
+*/
+ /// <summary>
+ /// true if the list is currently sorted.
+ /// </summary>
+ /// <seealso cref="Sort()"/>
+ public bool Sorted
+ {
+ get { return _sorted; }
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default constructor for the collection class
+ /// </summary>
+ public PointPairList()
+ {
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Constructor to initialize the PointPairList from two arrays of
+ /// type double.
+ /// </summary>
+ public PointPairList( double[] x, double[] y )
+ {
+ Add( x, y );
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Constructor to initialize the PointPairList from an IPointList
+ /// </summary>
+ public PointPairList( IPointList list )
+ {
+ int count = list.Count;
+ for ( int i = 0; i < count; i++ )
+ Add( list[i] );
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Constructor to initialize the PointPairList from three arrays of
+ /// type double.
+ /// </summary>
+ public PointPairList( double[] x, double[] y, double[] baseVal )
+ {
+ Add( x, y, baseVal );
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The PointPairList from which to copy</param>
+ public PointPairList( PointPairList rhs )
+ {
+ Add( rhs );
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public PointPairList Clone()
+ {
+ return new PointPairList( this );
+ }
+
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Add a <see cref="PointPair"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="point">The <see cref="PointPair"/> object to
+ /// be added</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ public new void Add( PointPair point )
+ {
+ _sorted = false;
+ //base.Add( new PointPair( point ) );
+ base.Add( point.Clone() );
+ }
+
+ /// <summary>
+ /// Add a <see cref="PointPairList"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="pointList">A reference to the <see cref="PointPairList"/> object to
+ /// be added</param>
+ /// <returns>The zero-based ordinal index where the last point was added in the list,
+ /// or -1 if no points were added.</returns>
+ public void Add( PointPairList pointList )
+ {
+ foreach ( PointPair point in pointList )
+ Add( point );
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Add a set of points to the PointPairList from two arrays of type double.
+ /// If either array is null, then a set of ordinal values is automatically
+ /// generated in its place (see <see cref="AxisType.Ordinal"/>.
+ /// If the arrays are of different size, then the larger array prevails and the
+ /// smaller array is padded with <see cref="PointPairBase.Missing"/> values.
+ /// </summary>
+ /// <param name="x">A double[] array of X values</param>
+ /// <param name="y">A double[] array of Y values</param>
+ /// <returns>The zero-based ordinal index where the last point was added in the list,
+ /// or -1 if no points were added.</returns>
+ public void Add( double[] x, double[] y )
+ {
+ int len = 0;
+
+ if ( x != null )
+ len = x.Length;
+ if ( y != null && y.Length > len )
+ len = y.Length;
+
+ for ( int i=0; i<len; i++ )
+ {
+ PointPair point = new PointPair( 0, 0, 0 );
+ if ( x == null )
+ point.X = (double) i + 1.0;
+ else if ( i < x.Length )
+ point.X = x[i];
+ else
+ point.X = PointPair.Missing;
+
+ if ( y == null )
+ point.Y = (double) i + 1.0;
+ else if ( i < y.Length )
+ point.Y = y[i];
+ else
+ point.Y = PointPair.Missing;
+
+ base.Add( point );
+ }
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Add a set of points to the <see cref="PointPairList"/> from three arrays of type double.
+ /// If the X or Y array is null, then a set of ordinal values is automatically
+ /// generated in its place (see <see cref="AxisType.Ordinal"/>. If the <see paramref="baseVal"/>
+ /// is null, then it is set to zero.
+ /// If the arrays are of different size, then the larger array prevails and the
+ /// smaller array is padded with <see cref="PointPairBase.Missing"/> values.
+ /// </summary>
+ /// <param name="x">A double[] array of X values</param>
+ /// <param name="y">A double[] array of Y values</param>
+ /// <param name="z">A double[] array of Z or lower-dependent axis values</param>
+ /// <returns>The zero-based ordinal index where the last point was added in the list,
+ /// or -1 if no points were added.</returns>
+ public void Add( double[] x, double[] y, double[] z )
+ {
+ int len = 0;
+
+ if ( x != null )
+ len = x.Length;
+ if ( y != null && y.Length > len )
+ len = y.Length;
+ if ( z != null && z.Length > len )
+ len = z.Length;
+
+ for ( int i=0; i<len; i++ )
+ {
+ PointPair point = new PointPair();
+
+ if ( x == null )
+ point.X = (double) i + 1.0;
+ else if ( i < x.Length )
+ point.X = x[i];
+ else
+ point.X = PointPair.Missing;
+
+ if ( y == null )
+ point.Y = (double) i + 1.0;
+ else if ( i < y.Length )
+ point.Y = y[i];
+ else
+ point.Y = PointPair.Missing;
+
+ if ( z == null )
+ point.Z = (double) i + 1.0;
+ else if ( i < z.Length )
+ point.Z = z[i];
+ else
+ point.Z = PointPair.Missing;
+
+ base.Add( point );
+ }
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Add a single point to the <see cref="PointPairList"/> from values of type double.
+ /// </summary>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ public void Add( double x, double y )
+ {
+ _sorted = false;
+ PointPair point = new PointPair( x, y );
+ base.Add( point );
+ }
+
+ /// <summary>
+ /// Add a single point to the <see cref="PointPairList"/> from values of type double.
+ /// </summary>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="tag">The Tag value for the PointPair</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ public void Add( double x, double y, string tag )
+ {
+ _sorted = false;
+ PointPair point = new PointPair( x, y, tag );
+ base.Add( point );
+ }
+
+ /// <summary>
+ /// Add a single point to the <see cref="PointPairList"/> from values of type double.
+ /// </summary>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="z">The Z or lower dependent axis value</param>
+ /// <returns>The zero-based ordinal index where the point was added
+ /// in the list.</returns>
+ public void Add( double x, double y, double z )
+ {
+ _sorted = false;
+ PointPair point = new PointPair( x, y, z );
+ base.Add( point );
+ }
+
+ /// <summary>
+ /// Add a single point to the <see cref="PointPairList"/> from values of type double.
+ /// </summary>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="z">The Z or lower dependent axis value</param>
+ /// <param name="tag">The Tag value for the PointPair</param>
+ /// <returns>The zero-based ordinal index where the point was added
+ /// in the list.</returns>
+ public void Add( double x, double y, double z, string tag )
+ {
+ _sorted = false;
+ PointPair point = new PointPair( x, y, z, tag );
+ base.Add( point );
+ }
+
+ /// <summary>
+ /// Add a <see cref="PointPair"/> object to the collection at the specified,
+ /// zero-based, index location.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based ordinal index where the point is to be added in the list.
+ /// </param>
+ /// <param name="point">
+ /// The <see cref="PointPair"/> object to be added.
+ /// </param>
+ public new void Insert( int index, PointPair point )
+ {
+ _sorted = false;
+ base.Insert( index, point );
+ }
+
+ /// <summary>
+ /// Add a single point (from values of type double ) to the <see cref="PointPairList"/> at the specified,
+ /// zero-based, index location.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based ordinal index where the point is to be added in the list.
+ /// </param>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ public void Insert( int index, double x, double y )
+ {
+ _sorted = false;
+ base.Insert( index, new PointPair( x, y ) );
+ }
+
+ /// <summary>
+ /// Add a single point (from values of type double ) to the <see cref="PointPairList"/> at the specified,
+ /// zero-based, index location.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based ordinal index where the point is to be added in the list.
+ /// </param>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="z">The Z or lower dependent axis value</param>
+ public void Insert( int index, double x, double y, double z )
+ {
+ _sorted = false;
+ Insert( index, new PointPair( x, y, z ) );
+ }
+ /*
+ /// <summary>
+ /// Remove the specified <see cref="PointPair"/> object from the collection based
+ /// the point values (must match exactly).
+ /// </summary>
+ /// <param name="pt">
+ /// A <see cref="PointPair"/> that is to be removed by value.
+ /// </param>
+ /// <seealso cref="IList.Remove"/>
+ public void Remove( PointPair pt )
+ {
+ List.Remove( pt );
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the specified
+ /// <see cref="PointPair"/> in the collection.
+ /// </summary>
+ /// <param name="pt">The <see cref="PointPair"/> object that is to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="PointPair"/>, or -1 if the <see cref="PointPair"/>
+ /// is not in the list</returns>
+ /// <seealso cref="IList.IndexOf"/>
+ public int IndexOf( PointPair pt )
+ {
+ return List.IndexOf( pt );
+ }
+ */
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="PointPair"/> with the specified label <see cref="PointPair.Tag"/>.
+ /// </summary>
+ /// <remarks>The <see cref="PointPair.Tag"/> object must be of type <see cref="String"/>
+ /// for this method to find it.</remarks>
+ /// <param name="label">The <see cref="String"/> label that is in the
+ /// <see cref="PointPair.Tag"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="PointPair"/>,
+ /// or -1 if the <see cref="PointPair"/> is not in the list</returns>
+ public int IndexOfTag( string label )
+ {
+ int iPt = 0;
+ foreach ( PointPair p in this )
+ {
+ if ( p.Tag is string && String.Compare( (string) p.Tag, label, true ) == 0 )
+ return iPt;
+ iPt++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Compare two <see cref="PointPairList"/> objects to see if they are equal.
+ /// </summary>
+ /// <remarks>Equality is based on equal count of <see cref="PointPair"/> items, and
+ /// each individual <see cref="PointPair"/> must be equal (as per the
+ /// <see cref="PointPair.Equals"/> method.</remarks>
+ /// <param name="obj">The <see cref="PointPairList"/> to be compared with for equality.</param>
+ /// <returns>true if the <see cref="PointPairList"/> objects are equal, false otherwise.</returns>
+ public override bool Equals( object obj )
+ {
+ PointPairList rhs = obj as PointPairList;
+ if( this.Count != rhs.Count )
+ return false;
+
+ for( int i=0; i<this.Count; i++ )
+ {
+ if( !this[i].Equals(rhs[i]) )
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Return the HashCode from the base class.
+ /// </summary>
+ /// <returns></returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode ();
+ }
+
+ /// <summary>
+ /// Sorts the list according to the point x values. Will not sort the
+ /// list if the list is already sorted.
+ /// </summary>
+ /// <returns>If the list was sorted before sort was called</returns>
+ public new bool Sort()
+ {
+ // if it is already sorted we don't have to sort again
+ if ( _sorted )
+ return true;
+
+ Sort( new PointPair.PointPairComparer( SortType.XValues ) );
+ return false;
+ }
+
+ /// <summary>
+ /// Sorts the list according to the point values . Will not sort the
+ /// list if the list is already sorted.
+ /// </summary>
+ /// <param name="type"></param> The <see cref = "SortType"/>
+ ///used to determine whether the X or Y values will be used to sort
+ ///the list
+ /// <returns>If the list was sorted before sort was called</returns>
+ public bool Sort( SortType type)
+ {
+ // if it is already sorted we don't have to sort again
+ if ( _sorted )
+ return true;
+
+ this.Sort( new PointPair.PointPairComparer( type ) );
+
+ return false;
+ }
+
+ /// <summary>
+ /// Set the X values for this <see cref="PointPairList"/> from the specified
+ /// array of double values.
+ /// </summary>
+ /// <remarks>
+ /// If <see paramref="x"/> has more values than
+ /// this list, then the extra values will be ignored. If <see paramref="x"/>
+ /// has less values, then the corresponding <see cref="PointPairList"/> values
+ /// will not be changed. That is, if the <see cref="PointPairList"/> has 20 values
+ /// and <see paramref="x"/> has 15 values, then the first 15 values of the
+ /// <see cref="PointPairList"/> will be changed, and the last 5 values will not be
+ /// changed.
+ /// </remarks>
+ /// <param name="x">An array of double values that will replace the existing X
+ /// values in the <see cref="PointPairList"/>.</param>
+ public void SetX( double[] x )
+ {
+ for ( int i=0; i<x.Length; i++ )
+ {
+ if ( i < this.Count )
+ this[i].X = x[i];
+ }
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Set the Y values for this <see cref="PointPairList"/> from the specified
+ /// array of double values.
+ /// </summary>
+ /// <remarks>
+ /// If <see paramref="y"/> has more values than
+ /// this list, then the extra values will be ignored. If <see paramref="y"/>
+ /// has less values, then the corresponding <see cref="PointPairList"/> values
+ /// will not be changed. That is, if the <see cref="PointPairList"/> has 20 values
+ /// and <see paramref="y"/> has 15 values, then the first 15 values of the
+ /// <see cref="PointPairList"/> will be changed, and the last 5 values will not be
+ /// changed.
+ /// </remarks>
+ /// <param name="y">An array of double values that will replace the existing Y
+ /// values in the <see cref="PointPairList"/>.</param>
+ public void SetY( double[] y )
+ {
+ for ( int i=0; i<y.Length; i++ )
+ {
+ if ( i < this.Count )
+ this[i].Y = y[i];
+ }
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Set the Z values for this <see cref="PointPairList"/> from the specified
+ /// array of double values.
+ /// </summary>
+ /// <remarks>
+ /// If <see paramref="z"/> has more values than
+ /// this list, then the extra values will be ignored. If <see paramref="z"/>
+ /// has less values, then the corresponding <see cref="PointPairList"/> values
+ /// will not be changed. That is, if the <see cref="PointPairList"/> has 20 values
+ /// and <see paramref="z"/> has 15 values, then the first 15 values of the
+ /// <see cref="PointPairList"/> will be changed, and the last 5 values will not be
+ /// changed.
+ /// </remarks>
+ /// <param name="z">An array of double values that will replace the existing Z
+ /// values in the <see cref="PointPairList"/>.</param>
+ public void SetZ( double[] z )
+ {
+ for ( int i=0; i<z.Length; i++ )
+ {
+ if ( i < this.Count )
+ this[i].Z = z[i];
+ }
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Add the Y values from the specified <see cref="PointPairList"/> object to this
+ /// <see cref="PointPairList"/>. If <see paramref="sumList"/> has more values than
+ /// this list, then the extra values will be ignored. If <see paramref="sumList"/>
+ /// has less values, the missing values are assumed to be zero.
+ /// </summary>
+ /// <param name="sumList">A reference to the <see cref="PointPairList"/> object to
+ /// be summed into the this <see cref="PointPairList"/>.</param>
+ public void SumY( PointPairList sumList )
+ {
+ for ( int i=0; i<this.Count; i++ )
+ {
+ if ( i < sumList.Count )
+ this[i].Y += sumList[i].Y;
+ }
+
+ //sorted = false;
+ }
+
+ /// <summary>
+ /// Add the X values from the specified <see cref="PointPairList"/> object to this
+ /// <see cref="PointPairList"/>. If <see paramref="sumList"/> has more values than
+ /// this list, then the extra values will be ignored. If <see paramref="sumList"/>
+ /// has less values, the missing values are assumed to be zero.
+ /// </summary>
+ /// <param name="sumList">A reference to the <see cref="PointPairList"/> object to
+ /// be summed into the this <see cref="PointPairList"/>.</param>
+ public void SumX( PointPairList sumList )
+ {
+ for ( int i=0; i<this.Count; i++ )
+ {
+ if ( i < sumList.Count )
+ this[i].X += sumList[i].X;
+ }
+
+ _sorted = false;
+ }
+
+ /// <summary>
+ /// Linearly interpolate the data to find an arbitraty Y value that corresponds to the specified X value.
+ /// </summary>
+ /// <remarks>
+ /// This method uses linear interpolation with a binary search algorithm. It therefore
+ /// requires that the x data be monotonically increasing. Missing values are not allowed. This
+ /// method will extrapolate outside the range of the PointPairList if necessary.
+ /// </remarks>
+ /// <param name="xTarget">The target X value on which to interpolate</param>
+ /// <returns>The Y value that corresponds to the <see paramref="xTarget"/> value.</returns>
+ public double InterpolateX( double xTarget )
+ {
+ int lo, mid, hi;
+ if ( this.Count < 2 )
+ throw new Exception( "Error: Not enough points in curve to interpolate" );
+
+ if ( xTarget <= this[0].X )
+ {
+ lo = 0;
+ hi = 1;
+ }
+ else if ( xTarget >= this[this.Count-1].X )
+ {
+ lo = this.Count - 2;
+ hi = this.Count - 1;
+ }
+ else
+ {
+ // if x is within the bounds of the x table, then do a binary search
+ // in the x table to find table entries that bound the x value
+ lo = 0;
+ hi = this.Count - 1;
+
+ // limit to 1000 loops to avoid an infinite loop problem
+ int j;
+ for ( j=0; j<1000 && hi > lo + 1; j++ )
+ {
+ mid = ( hi + lo ) / 2;
+ if ( xTarget > this[mid].X )
+ lo = mid;
+ else
+ hi = mid;
+ }
+
+ if ( j >= 1000 )
+ throw new Exception( "Error: Infinite loop in interpolation" );
+ }
+
+ return ( xTarget - this[lo].X ) / ( this[hi].X - this[lo].X ) *
+ ( this[hi].Y - this[lo].Y ) + this[lo].Y;
+
+ }
+
+ /// <summary>
+ /// Use Cardinal Splines to Interpolate the data to find an arbitraty Y value that corresponds to
+ /// the specified X value.
+ /// </summary>
+ /// <remarks>
+ /// This method uses cardinal spline interpolation with a binary search algorithm. It therefore
+ /// requires that the x data be monotonically increasing. Missing values are not allowed. This
+ /// method will not extrapolate outside the range of the PointPairList (it returns
+ /// <see cref="PointPairBase.Missing"/> if extrapolation would be required). WARNING: Cardinal
+ /// spline interpolation can generate curves with non-unique X values for higher tension
+ /// settings. That is, there may be multiple X values for the same Y value. This routine
+ /// follows the path of the spline curve until it reaches the FIRST OCCURRENCE of the
+ /// target X value. It does not check to see if other solutions are possible.
+ /// </remarks>
+ /// <param name="xTarget">The target X value on which to interpolate</param>
+ /// <param name="tension">The tension setting that controls the curvature of the spline fit.
+ /// Typical values are between 0 and 1, where 0 is a linear fit, and 1 is lots of "roundness".
+ /// Values greater than 1 may give odd results.
+ /// </param>
+ /// <returns>The Y value that corresponds to the <see paramref="xTarget"/> value.</returns>
+ public double SplineInterpolateX( double xTarget, double tension )
+ {
+ // Scale the tension value to be compatible with the GDI+ values
+ tension /= 3.0;
+
+ int lo, mid, hi;
+ if ( this.Count < 2 )
+ throw new Exception( "Error: Not enough points in curve to interpolate" );
+
+ // Extrapolation not allowed
+ if ( xTarget <= this[0].X || xTarget >= this[this.Count-1].X )
+ return PointPair.Missing;
+ else
+ {
+ // if x is within the bounds of the x table, then do a binary search
+ // in the x table to find table entries that bound the x value
+ lo = 0;
+ hi = this.Count - 1;
+
+ // limit to 1000 loops to avoid an infinite loop problem
+ int j;
+ for ( j=0; j<1000 && hi > lo + 1; j++ )
+ {
+ mid = ( hi + lo ) / 2;
+ if ( xTarget > this[mid].X )
+ lo = mid;
+ else
+ hi = mid;
+ }
+
+ if ( j >= 1000 )
+ throw new Exception( "Error: Infinite loop in interpolation" );
+ }
+
+ // At this point, we know the two bounding points around our point of interest
+ // We need the four points that surround our point
+
+ double X0, X1, X2, X3;
+ double Y0, Y1, Y2, Y3;
+ double B0, B1, B2, B3;
+
+ X1 = this[lo].X;
+ X2 = this[hi].X;
+ Y1 = this[lo].Y;
+ Y2 = this[hi].Y;
+
+ // if we are at either the beginning of the table or the end, then make up a before
+ // and/or after point to fill in the four points
+ if ( lo == 0 )
+ {
+ X0 = X1 - ( X2 - X1 )/3;
+ Y0 = Y1 - ( Y2 - Y1 )/3;
+ }
+ else
+ {
+ X0 = this[lo-1].X;
+ Y0 = this[lo-1].Y;
+ }
+
+ if ( hi == this.Count - 1 )
+ {
+ X3 = X2 + ( X2 - X1 )/3;
+ Y3 = Y2 + ( Y2 - Y1 )/3;
+ }
+ else
+ {
+ X3 = this[hi+1].X;
+ Y3 = this[hi+1].Y;
+ }
+
+ double newX, newY,
+ lastX = X1,
+ lastY = Y1;
+
+ // Do 100 steps to find the result
+ for ( double t=0.01; t<=1; t+=0.01 )
+ {
+ B0 = (1 - t) * (1 - t) * (1 - t);
+ B1 = 3.0 * t * (1 - t) * (1 - t);
+ B2 = 3.0 * t * t * (1 - t);
+ B3 = t * t * t;
+
+ newX = X1 * B0 + (X1 + (X2 - X0) * tension) * B1 +
+ (X2 - (X3 - X1) * tension) * B2 + X2 * B3;
+ newY = Y1 * B0 + (Y1 + (Y2 - Y0) * tension) * B1 +
+ (Y2 - (Y3 - Y1) * tension) * B2 + Y2 * B3;
+
+ // We are looking for the first X that exceeds the target
+ if ( newX >= xTarget )
+ {
+ // We now have two bounding X values around our target
+ // use linear interpolation to minimize the discretization
+ // error.
+ return ( xTarget - lastX ) / ( newX - lastX ) *
+ ( newY - lastY ) + lastY;
+ }
+
+ lastX = newX;
+ lastY = newY;
+ }
+
+ // This should never happen
+ return Y2;
+ }
+
+ /// <summary>
+ /// Linearly interpolate the data to find an arbitraty X value that corresponds to the specified Y value.
+ /// </summary>
+ /// <remarks>
+ /// This method uses linear interpolation with a binary search algorithm. It therefore
+ /// requires that the Y data be monotonically increasing. Missing values are not allowed. This
+ /// method will extrapolate outside the range of the PointPairList if necessary.
+ /// </remarks>
+ /// <param name="yTarget">The target Y value on which to interpolate</param>
+ /// <returns>The X value that corresponds to the <see paramref="yTarget"/> value.</returns>
+ public double InterpolateY( double yTarget )
+ {
+ int lo, mid, hi;
+ if ( this.Count < 2 )
+ throw new Exception( "Error: Not enough points in curve to interpolate" );
+
+ if ( yTarget <= this[0].Y )
+ {
+ lo = 0;
+ hi = 1;
+ }
+ else if ( yTarget >= this[this.Count-1].Y )
+ {
+ lo = this.Count - 2;
+ hi = this.Count - 1;
+ }
+ else
+ {
+ // if y is within the bounds of the y table, then do a binary search
+ // in the y table to find table entries that bound the y value
+ lo = 0;
+ hi = this.Count - 1;
+
+ // limit to 1000 loops to avoid an infinite loop problem
+ int j;
+ for ( j=0; j<1000 && hi > lo + 1; j++ )
+ {
+ mid = ( hi + lo ) / 2;
+ if ( yTarget > this[mid].Y )
+ lo = mid;
+ else
+ hi = mid;
+ }
+
+ if ( j >= 1000 )
+ throw new Exception( "Error: Infinite loop in interpolation" );
+ }
+
+ return ( yTarget - this[lo].Y ) / ( this[hi].Y - this[lo].Y ) *
+ ( this[hi].X - this[lo].X ) + this[lo].X;
+
+ }
+
+ /// <summary>
+ /// Use linear regression to form a least squares fit of an existing
+ /// <see cref="IPointList"/> instance.
+ /// </summary>
+ /// <remarks>The output <see cref="PointPairList" /> will cover the
+ /// same X range of data as the original dataset.
+ /// </remarks>
+ /// <param name="points">An <see cref="IPointList" /> instance containing
+ /// the data to be regressed.</param>
+ /// <param name="pointCount">The number of desired points to be included
+ /// in the resultant <see cref="PointPairList" />.
+ /// </param>
+ /// <returns>A new <see cref="PointPairList" /> containing the resultant
+ /// data fit.
+ /// </returns>
+ public PointPairList LinearRegression( IPointList points, int pointCount )
+ {
+ double minX = double.MaxValue;
+ double maxX = double.MinValue;
+
+ for ( int i=0; i<points.Count; i++ )
+ {
+ PointPair pt = points[i];
+
+ if ( !pt.IsInvalid )
+ {
+ minX = pt.X < minX ? pt.X : minX;
+ maxX = pt.X > maxX ? pt.X : maxX;
+ }
+ }
+
+ return LinearRegression( points, pointCount, minX, maxX );
+ }
+
+
+ /// <summary>
+ /// Use linear regression to form a least squares fit of an existing
+ /// <see cref="IPointList"/> instance.
+ /// </summary>
+ /// <param name="points">An <see cref="IPointList" /> instance containing
+ /// the data to be regressed.</param>
+ /// <param name="pointCount">The number of desired points to be included
+ /// in the resultant <see cref="PointPairList" />.
+ /// </param>
+ /// <param name="minX">The minimum X value of the resultant
+ /// <see cref="PointPairList" />.</param>
+ /// <param name="maxX">The maximum X value of the resultant
+ /// <see cref="PointPairList" />.</param>
+ /// <returns>A new <see cref="PointPairList" /> containing the resultant
+ /// data fit.
+ /// </returns>
+ /// <author> Brian Chappell - lazarusds
+ /// modified by John Champion</author>
+ public PointPairList LinearRegression( IPointList points, int pointCount,
+ double minX, double maxX )
+ {
+ double x = 0, y = 0, xx = 0, xy = 0, count = 0;
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ PointPair pt = points[i];
+ if ( !pt.IsInvalid )
+ {
+ x += points[i].X;
+ y += points[i].Y;
+ xx += points[i].X * points[i].X;
+ xy += points[i].X * points[i].Y;
+ count++;
+ }
+ }
+
+ if ( count < 2 || maxX - minX < 1e-20 )
+ return null;
+
+ double slope = ( count * xy - x * y ) / ( count * xx - x * x );
+ double intercept = ( y - slope * x ) / count;
+
+ PointPairList newPoints = new PointPairList();
+ double stepSize = ( maxX - minX ) / pointCount;
+ double value = minX;
+ for ( int i = 0; i < pointCount; i++ )
+ {
+ newPoints.Add( new PointPair( value, value * slope + intercept ) );
+ value += stepSize;
+ }
+
+ return newPoints;
+ }
+
+
+ #endregion
+ }
+}
+
+
diff --git a/ZedGraph/PolyObj.cs b/ZedGraph/PolyObj.cs
new file mode 100644
index 0000000..5f446f3
--- /dev/null
+++ b/ZedGraph/PolyObj.cs
@@ -0,0 +1,335 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents a bordered and/or filled polygon object on
+ /// the graph. A list of <see cref="PolyObj"/> objects is maintained by
+ /// the <see cref="GraphObjList"/> collection class.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-01-25 07:56:09 $ </version>
+ [Serializable]
+ public class PolyObj : BoxObj, ICloneable, ISerializable
+ {
+
+ #region Fields
+
+ private PointD[] _points;
+
+ /// <summary>
+ /// private value that determines if the polygon will be automatically closed.
+ /// true to close the figure, false to leave it "open." Use the public property
+ /// <see cref="IsClosedFigure" /> to access this value.
+ /// </summary>
+ private bool _isClosedFigure = true;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="PointD"/> array that defines
+ /// the polygon. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/>.
+ /// </summary>
+ public PointD[] Points
+ {
+ get { return _points; }
+ set { _points = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the polygon will be automatically closed.
+ /// true to close the figure, false to leave it "open."
+ /// </summary>
+ /// <remarks>
+ /// This boolean determines whether or not the CloseFigure() method will be called
+ /// to fully close the path of the polygon. This value defaults to true, and for any
+ /// closed figure it should fine. If you want to draw a line that does not close into
+ /// a shape, then you should set this value to false. For a figure that is naturally
+ /// closed (e.g., the first point of the polygon is the same as the last point),
+ /// leaving this value set to false may result in minor pixel artifacts due to
+ /// rounding.
+ /// </remarks>
+ public bool IsClosedFigure
+ {
+ get { return _isClosedFigure; }
+ set { _isClosedFigure = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <overloads>Constructors for the <see cref="PolyObj"/> object</overloads>
+ /// <summary>
+ /// A constructor that allows the position, border color, and solid fill color
+ /// of the <see cref="PolyObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="borderColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the box border</param>
+ /// <param name="fillColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the box fill (will be a solid color fill)</param>
+ /// <param name="points">The <see cref="PointD"/> array that defines
+ /// the polygon. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/>.
+ /// </param>
+ public PolyObj( PointD[] points, Color borderColor, Color fillColor ) :
+ base( 0, 0, 1, 1, borderColor, fillColor )
+ {
+ _points = points;
+ }
+
+ /// <summary>
+ /// A constructor that allows the position
+ /// of the <see cref="PolyObj"/> to be pre-specified. Other properties are defaulted.
+ /// </summary>
+ /// <param name="points">The <see cref="PointD"/> array that defines
+ /// the polygon. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/>.
+ /// </param>
+ public PolyObj( PointD[] points ) : base( 0, 0, 1, 1 )
+ {
+ _points = points;
+ }
+
+ /// <summary>
+ /// A default constructor that creates a <see cref="PolyObj"/> from an empty
+ /// <see cref="PointD"/> array. Other properties are defaulted.
+ /// </summary>
+ public PolyObj() : this( new PointD[0] )
+ {
+ }
+
+ /// <summary>
+ /// A constructor that allows the position, border color, and two-color
+ /// gradient fill colors
+ /// of the <see cref="PolyObj"/> to be pre-specified.
+ /// </summary>
+ /// <param name="borderColor">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the box border</param>
+ /// <param name="fillColor1">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the start of the box gradient fill</param>
+ /// <param name="fillColor2">An arbitrary <see cref="System.Drawing.Color"/> specification
+ /// for the end of the box gradient fill</param>
+ /// <param name="points">The <see cref="PointD"/> array that defines
+ /// the polygon. This will be in units determined by
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/>.
+ /// </param>
+ public PolyObj( PointD[] points, Color borderColor,
+ Color fillColor1, Color fillColor2 ) :
+ base( 0, 0, 1, 1, borderColor, fillColor1, fillColor2 )
+ {
+ _points = points;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="PolyObj"/> object from which to copy</param>
+ public PolyObj( PolyObj rhs ) : base( rhs )
+ {
+ rhs._points = (PointD[]) _points.Clone();
+ rhs._isClosedFigure = _isClosedFigure;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new PolyObj Clone()
+ {
+ return new PolyObj( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected PolyObj( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+
+ _points = (PointD[]) info.GetValue( "points", typeof(PointD[]) );
+
+ if ( schema3 >= 11 )
+ _isClosedFigure = info.GetBoolean( "isClosedFigure" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema3", schema3 );
+
+ info.AddValue( "points", _points );
+ info.AddValue( "isClosedFigure", _isClosedFigure );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this object to the specified <see cref="Graphics"/> device.
+ /// </summary>
+ /// <remarks>
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </remarks>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ if ( _points != null && _points.Length > 1 )
+ {
+ using ( GraphicsPath path = MakePath( pane ) )
+ {
+ // Fill or draw the symbol as required
+ if ( _fill.IsVisible )
+ {
+ using ( Brush brush = this.Fill.MakeBrush( path.GetBounds() ) )
+ g.FillPath( brush, path );
+ }
+
+ if ( _border.IsVisible )
+ {
+ using ( Pen pen = _border.GetPen( pane, scaleFactor ) )
+ g.DrawPath( pen, path );
+ }
+ }
+ }
+ }
+
+ internal GraphicsPath MakePath( PaneBase pane )
+ {
+ GraphicsPath path = new GraphicsPath();
+ bool first = true;
+ PointF lastPt = new PointF();
+
+ foreach( PointD pt in _points )
+ {
+ // Convert the coordinates from the user coordinate system
+ // to the screen coordinate system
+ // Offset the points by the location value
+ PointF pixPt = Location.Transform( pane, pt.X + _location.X, pt.Y + _location.Y,
+ _location.CoordinateFrame );
+
+ if ( Math.Abs( pixPt.X ) < 100000 &&
+ Math.Abs( pixPt.Y ) < 100000 )
+ {
+ if ( first )
+ first = false;
+ else
+ path.AddLine( lastPt, pixPt );
+
+ lastPt = pixPt;
+ }
+ }
+
+ if ( _isClosedFigure )
+ path.CloseFigure();
+
+ return path;
+ }
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="PolyObj"/>.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ if ( _points != null && _points.Length > 1 )
+ {
+ if ( ! base.PointInBox(pt, pane, g, scaleFactor ) )
+ return false;
+
+ using ( GraphicsPath path = MakePath( pane ) )
+ return path.IsVisible( pt );
+ }
+ else
+ return false;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/RadarPointList.cs b/ZedGraph/RadarPointList.cs
new file mode 100644
index 0000000..c379a5c
--- /dev/null
+++ b/ZedGraph/RadarPointList.cs
@@ -0,0 +1,216 @@
+//============================================================================
+//RadarPointList Class
+//Copyright � 2006 John Champion, Jerry Vos
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class containing a set of data values to be plotted as a RadarPlot.
+ /// This class will effectively convert the data into <see cref="PointPair" /> objects
+ /// by converting the polar coordinates to rectangular coordinates
+ /// </summary>
+ /// <seealso cref="BasicArrayPointList" />
+ /// <seealso cref="IPointList" />
+ /// <seealso cref="IPointListEdit" />
+ ///
+ /// <author>Jerry Vos and John Champion</author>
+ /// <version> $Revision: 3.5 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ public class RadarPointList : List<PointPair>, IPointList, IPointListEdit
+ {
+
+ #region Fields
+ /// <summary>
+ /// Default to clockwise rotation as this is the standard for radar charts
+ /// </summary>
+ private bool _clockwise = true;
+
+ /// <summary>
+ /// Default to 90 degree rotation so main axis is in the 12 o'clock position,
+ /// which is the standard for radar charts.
+ /// </summary>
+ private double _rotation = 90;
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="PointPair"/> object by
+ /// its ordinal position in the list. This method does the calculations
+ /// to convert the data from polar to rectangular coordinates.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="PointPair"/> object to be accessed.</param>
+ /// <value>A <see cref="PointPair"/> object reference.</value>
+ public new PointPair this[int index]
+ {
+ get
+ {
+ int count = this.Count;
+ // The last point is a repeat of the first point
+ if ( index == count - 1 )
+ index = 0;
+
+ if ( index < 0 || index >= count )
+ return null;
+
+ PointPair pt = (PointPair)base[index];
+// double theta = (double) index / (double) count * 2.0 * Math.PI;
+ double rotationRadians = _rotation * Math.PI / 180;
+ double theta = rotationRadians + ( _clockwise ? -1.0d : 1.0d ) *
+ ( (double) index / (double) (count-1) * 2.0 * Math.PI);
+ double x = pt.Y * Math.Cos( theta );
+ double y = pt.Y * Math.Sin( theta );
+ return new PointPair( x, y, pt.Z, (string) pt.Tag );
+ }
+ set
+ {
+ int count = this.Count;
+ // The last point is a repeat of the first point
+ if ( index == count - 1 )
+ index = 0;
+
+ if ( index < 0 || index >= count )
+ return;
+
+ PointPair pt = (PointPair)base[index];
+ pt.Y = Math.Sqrt( value.X * value.X + value.Y * value.Y );
+ }
+ }
+
+ /// <summary>
+ /// Indicates if points should be added in clockwise or counter-clockwise order
+ /// </summary>
+ public bool Clockwise
+ {
+ get { return _clockwise; }
+ set { _clockwise = value; }
+ }
+
+ /// <summary>
+ /// Sets the angular rotation (starting angle) for the initial axis
+ /// </summary>
+ public double Rotation
+ {
+ get { return _rotation; }
+ set { _rotation = value; }
+ }
+
+ /// <summary>
+ /// Get the raw data
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ private PointPair GetAt( int index )
+ {
+ return base[index];
+ }
+
+ /// <summary>
+ /// gets the number of points available in the list
+ /// </summary>
+ public new int Count
+ {
+ get { return base.Count + 1; }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public RadarPointList() : base()
+ {
+ }
+
+ /// <summary>
+ /// Copy Constructor
+ /// </summary>
+ public RadarPointList( RadarPointList rhs )
+ {
+ for ( int i = 0; i < rhs.Count; i++ )
+ this.Add( rhs.GetAt(i) );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public RadarPointList Clone()
+ {
+ return new RadarPointList( this );
+ }
+
+
+ #endregion
+
+ #region Methods
+/*
+ * /// <summary>
+ /// Add the specified PointPair to the collection.
+ /// </summary>
+ /// <param name="pt">The PointPair to be added</param>
+ /// <returns>The ordinal position in the list where the point was added</returns>
+ public int Add( PointPair pt )
+ {
+ return List.Add( pt );
+ }
+
+ /// <summary>
+ /// Add a single point to the <see cref="RadarPointList"/> from a value of type double.
+ /// </summary>
+ /// <param name="r">The radial coordinate value</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ /// <seealso cref="IList.Add"/>
+ public int Add( double r )
+ {
+ return List.Add( new PointPair( PointPair.Missing, r ) );
+ }
+*/
+ /// <summary>
+ /// Add a single point to the <see cref="RadarPointList"/> from two values of type double.
+ /// </summary>
+ /// <param name="r">The radial coordinate value</param>
+ /// <param name="z">The 'Z' coordinate value, which is not normally used for plotting,
+ /// but can be used for <see cref="FillType.GradientByZ" /> type fills</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ public void Add( double r, double z )
+ {
+ Add( new PointPair( PointPair.Missing, r, z ) );
+ }
+
+ #endregion
+ }
+}
+
+
diff --git a/ZedGraph/RollingPointPairList.cs b/ZedGraph/RollingPointPairList.cs
new file mode 100644
index 0000000..853788c
--- /dev/null
+++ b/ZedGraph/RollingPointPairList.cs
@@ -0,0 +1,654 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2006 John Champion
+//RollingPointPairList class Copyright � 2006 by Colin Green
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that provides a rolling list of <see cref="PointPair" /> objects.
+ /// This is essentially a
+ /// first-in-first-out (FIFO) queue with a fixed capacity which allows 'rolling'
+ /// (or oscilloscope like) graphs to be be animated without having the overhead of an
+ /// ever-growing ArrayList.
+ ///
+ /// The queue is constructed with a fixed capacity and new points can be enqueued. When the
+ /// capacity is reached the oldest (first in) PointPair is overwritten. However, when
+ /// accessing via <see cref="IPointList" />, the <see cref="PointPair" /> objects are
+ /// seen in the order in which they were enqeued.
+ ///
+ /// RollingPointPairList supports data editing through the <see cref="IPointListEdit" />
+ /// interface.
+ ///
+ /// <author>Colin Green with mods by John Champion</author>
+ /// <version> $Date: 2007-11-05 04:33:26 $ </version>
+ /// </summary>
+ [Serializable]
+ public class RollingPointPairList : IPointList, ISerializable, IPointListEdit
+ {
+
+ #region Fields
+
+ /// <summary>
+ /// An array of PointPair objects that acts as the underlying buffer.
+ /// </summary>
+ protected PointPair[] _mBuffer;
+
+ /// <summary>
+ /// The index of the previously enqueued item. -1 if buffer is empty.
+ /// </summary>
+ protected int _headIdx;
+
+ /// <summary>
+ /// The index of the next item to be dequeued. -1 if buffer is empty.
+ /// </summary>
+ protected int _tailIdx;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructs an empty buffer with the specified capacity.
+ /// </summary>
+ /// <param name="capacity">Number of elements in the rolling list. This number
+ /// cannot be changed once the RollingPointPairList is constructed.</param>
+ public RollingPointPairList( int capacity )
+ : this( capacity, false )
+ {
+ _mBuffer = new PointPair[capacity];
+ _headIdx = _tailIdx = -1;
+ }
+
+ /// <summary>
+ /// Constructs an empty buffer with the specified capacity. Pre-allocates space
+ /// for all PointPair's in the list if <paramref name="preLoad"/> is true.
+ /// </summary>
+ /// <param name="capacity">Number of elements in the rolling list. This number
+ /// cannot be changed once the RollingPointPairList is constructed.</param>
+ /// <param name="preLoad">true to pre-allocate all PointPair instances in
+ /// the list, false otherwise. Note that in order to be memory efficient,
+ /// the <see cref="Add(double,double,double)"/> method should be used to add
+ /// data. Avoid the <see cref="Add(PointPair)"/> method.
+ /// </param>
+ /// <seealso cref="Add(double,double,double)"/>
+ public RollingPointPairList( int capacity, bool preLoad )
+ {
+ _mBuffer = new PointPair[capacity];
+ _headIdx = _tailIdx = -1;
+
+ if ( preLoad )
+ for ( int i = 0; i < capacity; i++ )
+ _mBuffer[i] = new PointPair();
+ }
+
+ /// <summary>
+ /// Constructs a buffer with a copy of the items within the provided
+ /// <see cref="IPointList" />.
+ /// The <see cref="Capacity" /> is set to the length of the provided list.
+ /// </summary>
+ /// <param name="rhs">The <see cref="IPointList" /> to be copied.</param>
+ public RollingPointPairList( IPointList rhs )
+ {
+ _mBuffer = new PointPair[rhs.Count];
+
+ for ( int i = 0; i < rhs.Count; i++ )
+ {
+ _mBuffer[i] = new PointPair( rhs[i] );
+ }
+
+ _headIdx = rhs.Count - 1;
+ _tailIdx = 0;
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets the capacity of the rolling buffer.
+ /// </summary>
+ public int Capacity
+ {
+ get { return _mBuffer.Length; }
+ }
+
+ /// <summary>
+ /// Gets the count of items within the rolling buffer. Note that this may be less than
+ /// the capacity.
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ if ( _headIdx == -1 )
+ return 0;
+
+ if ( _headIdx > _tailIdx )
+ return ( _headIdx - _tailIdx ) + 1;
+
+ if ( _tailIdx > _headIdx )
+ return ( _mBuffer.Length - _tailIdx ) + _headIdx + 1;
+
+ return 1;
+ }
+ }
+
+ /// <summary>
+ /// Gets a bolean that indicates if the buffer is empty.
+ /// Alternatively you can test Count==0.
+ /// </summary>
+ public bool IsEmpty
+ {
+ get { return _headIdx == -1; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="PointPair" /> at the specified index in the buffer.
+ /// </summary>
+ /// <remarks>
+ /// Index must be within the current size of the buffer, e.g., the set
+ /// method will not expand the buffer even if <see cref="Capacity" /> is available
+ /// </remarks>
+ public PointPair this[int index]
+ {
+ get
+ {
+ if ( index >= Count || index < 0 )
+ throw new ArgumentOutOfRangeException();
+
+ index += _tailIdx;
+ if ( index >= _mBuffer.Length )
+ index -= _mBuffer.Length;
+
+ return _mBuffer[index];
+ }
+ set
+ {
+ if ( index >= Count || index < 0 )
+ throw new ArgumentOutOfRangeException();
+
+ index += _tailIdx;
+ if ( index >= _mBuffer.Length )
+ index -= _mBuffer.Length;
+
+ _mBuffer[index] = value;
+ }
+
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public RollingPointPairList Clone()
+ {
+ return new RollingPointPairList( this );
+ }
+
+ /// <summary>
+ /// Clear the buffer of all <see cref="PointPair"/> objects.
+ /// Note that the <see cref="Capacity" /> remains unchanged.
+ /// </summary>
+ public void Clear()
+ {
+ _headIdx = _tailIdx = -1;
+ }
+
+ /// <summary>
+ /// Calculate that the next index in the buffer that should receive a new data point.
+ /// Note that this method actually advances the buffer, so a datapoint should be
+ /// added at _mBuffer[_headIdx].
+ /// </summary>
+ /// <returns>The index position of the new head element</returns>
+ private int GetNextIndex()
+ {
+ if ( _headIdx == -1 )
+ { // buffer is currently empty.
+ _headIdx = _tailIdx = 0;
+ }
+ else
+ {
+ // Determine the index to write to.
+ if ( ++_headIdx == _mBuffer.Length )
+ { // Wrap around.
+ _headIdx = 0;
+ }
+
+ if ( _headIdx == _tailIdx )
+ { // Buffer overflow. Increment tailIdx.
+ if ( ++_tailIdx == _mBuffer.Length )
+ { // Wrap around.
+ _tailIdx = 0;
+ }
+ }
+ }
+
+ return _headIdx;
+ }
+
+ /// <summary>
+ /// Add a <see cref="PointPair"/> onto the head of the queue,
+ /// overwriting old values if the buffer is full.
+ /// </summary>
+ /// <param name="item">The <see cref="PointPair" /> to be added.</param>
+ public void Add( PointPair item )
+ {
+ _mBuffer[ GetNextIndex() ] = item;
+ }
+
+ /// <summary>
+ /// Add an <see cref="IPointList"/> object to the head of the queue.
+ /// </summary>
+ /// <param name="pointList">A reference to the <see cref="IPointList"/> object to
+ /// be added</param>
+ public void Add( IPointList pointList )
+ { // A slightly more efficient approach would be to determine where the new points should placed within
+ // the buffer and to then copy them in directly - updating the head and tail indexes appropriately.
+ for ( int i = 0; i < pointList.Count; i++ )
+ Add( pointList[i] );
+ }
+
+ /// <summary>
+ /// Remove an old item from the tail of the queue.
+ /// </summary>
+ /// <returns>The removed item. Throws an <see cref="InvalidOperationException" />
+ /// if the buffer was empty.
+ /// Check the buffer's length (<see cref="Count" />) or the <see cref="IsEmpty" />
+ /// property to avoid exceptions.</returns>
+ public PointPair Remove()
+ {
+ if ( _tailIdx == -1 )
+ { // buffer is currently empty.
+ throw new InvalidOperationException( "buffer is empty." );
+ }
+
+ PointPair o = _mBuffer[_tailIdx];
+
+ if ( _tailIdx == _headIdx )
+ { // The buffer is now empty.
+ _headIdx = _tailIdx = -1;
+ return o;
+ }
+
+ if ( ++_tailIdx == _mBuffer.Length )
+ { // Wrap around.
+ _tailIdx = 0;
+ }
+
+ return o;
+ }
+
+ /// <summary>
+ /// Remove the <see cref="PointPair" /> at the specified index
+ /// </summary>
+ /// <remarks>
+ /// All items in the queue that lie after <paramref name="index"/> will
+ /// be shifted back by one, and the queue will be one item shorter.
+ /// </remarks>
+ /// <param name="index">The ordinal position of the item to be removed.
+ /// Throws an <see cref="ArgumentOutOfRangeException" /> if index is less than
+ /// zero or greater than or equal to <see cref="Count" />
+ /// </param>
+ public void RemoveAt( int index )
+ {
+ int count = this.Count;
+
+ if ( index >= count || index < 0 )
+ throw new ArgumentOutOfRangeException();
+
+ // shift all the items that lie after index back by 1
+ for ( int i = index + _tailIdx; i < _tailIdx + count - 1; i++ )
+ {
+ i = ( i >= _mBuffer.Length ) ? 0 : i;
+ int j = i + 1;
+ j = ( j >= _mBuffer.Length ) ? 0 : j;
+ _mBuffer[i] = _mBuffer[j];
+ }
+
+ // Remove the item from the head (it's been duplicated already)
+ Pop();
+ }
+
+ /// <summary>
+ /// Remove a range of <see cref="PointPair" /> objects starting at the specified index
+ /// </summary>
+ /// <remarks>
+ /// All items in the queue that lie after <paramref name="index"/> will
+ /// be shifted back, and the queue will be <paramref name="count" /> items shorter.
+ /// </remarks>
+ /// <param name="index">The ordinal position of the item to be removed.
+ /// Throws an <see cref="ArgumentOutOfRangeException" /> if index is less than
+ /// zero or greater than or equal to <see cref="Count" />
+ /// </param>
+ /// <param name="count">The number of items to be removed. Throws an
+ /// <see cref="ArgumentOutOfRangeException" /> if <paramref name="count" /> is less than zero
+ /// or greater than the total available items in the queue</param>
+ public void RemoveRange( int index, int count )
+ {
+ int totalCount = this.Count;
+
+ if ( index >= totalCount || index < 0 || count < 0 || count > totalCount )
+ throw new ArgumentOutOfRangeException();
+
+ for ( int i = 0; i < count; i++ )
+ this.RemoveAt( index );
+ }
+
+ /// <summary>
+ /// Pop an item off the head of the queue.
+ /// </summary>
+ /// <returns>The popped item. Throws an exception if the buffer was empty.</returns>
+ public PointPair Pop()
+ {
+ if ( _tailIdx == -1 )
+ { // buffer is currently empty.
+ throw new InvalidOperationException( "buffer is empty." );
+ }
+
+ PointPair o = _mBuffer[_headIdx];
+
+ if ( _tailIdx == _headIdx )
+ { // The buffer is now empty.
+ _headIdx = _tailIdx = -1;
+ return o;
+ }
+
+ if ( --_headIdx == -1 )
+ { // Wrap around.
+ _headIdx = _mBuffer.Length - 1;
+ }
+
+ return o;
+ }
+
+ /// <summary>
+ /// Peek at the <see cref="PointPair" /> item at the head of the queue.
+ /// </summary>
+ /// <returns>The <see cref="PointPair" /> item at the head of the queue.
+ /// Throws an <see cref="InvalidOperationException" /> if the buffer was empty.
+ /// </returns>
+ public PointPair Peek()
+ {
+ if ( _headIdx == -1 )
+ { // buffer is currently empty.
+ throw new InvalidOperationException( "buffer is empty." );
+ }
+
+ return _mBuffer[_headIdx];
+ }
+
+ #endregion
+
+ #region Auxilliary Methods
+
+ /// <summary>
+ /// Add a set of values onto the head of the queue,
+ /// overwriting old values if the buffer is full.
+ /// </summary>
+ /// <remarks>
+ /// This method is much more efficient that the <see cref="Add(PointPair)">Add(PointPair)</see>
+ /// method, since it does not require that a new PointPair instance be provided.
+ /// If the buffer already contains a <see cref="PointPair"/> at the head position,
+ /// then the x, y, z, and tag values will be copied into the existing PointPair.
+ /// Otherwise, a new PointPair instance must be created.
+ /// In this way, each PointPair position in the rolling list will only be allocated one time.
+ /// To truly be memory efficient, the <see cref="Remove" />, <see cref="RemoveAt" />,
+ /// and <see cref="Pop" /> methods should be avoided. Also, the <paramref name="tag"/> property
+ /// for this method should be null, since it is a reference type.
+ /// </remarks>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="z">The Z value</param>
+ /// <param name="tag">The Tag value for the PointPair</param>
+ public void Add( double x, double y, double z, object tag )
+ {
+ // advance the rolling list
+ GetNextIndex();
+
+ if ( _mBuffer[_headIdx] == null )
+ _mBuffer[_headIdx] = new PointPair( x, y, z, tag );
+ else
+ {
+ _mBuffer[_headIdx].X = x;
+ _mBuffer[_headIdx].Y = y;
+ _mBuffer[_headIdx].Z = z;
+ _mBuffer[_headIdx].Tag = tag;
+ }
+ }
+
+ /// <summary>
+ /// Add a set of values onto the head of the queue,
+ /// overwriting old values if the buffer is full.
+ /// </summary>
+ /// <remarks>
+ /// This method is much more efficient that the <see cref="Add(PointPair)">Add(PointPair)</see>
+ /// method, since it does not require that a new PointPair instance be provided.
+ /// If the buffer already contains a <see cref="PointPair"/> at the head position,
+ /// then the x, y, z, and tag values will be copied into the existing PointPair.
+ /// Otherwise, a new PointPair instance must be created.
+ /// In this way, each PointPair position in the rolling list will only be allocated one time.
+ /// To truly be memory efficient, the <see cref="Remove" />, <see cref="RemoveAt" />,
+ /// and <see cref="Pop" /> methods should be avoided.
+ /// </remarks>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ public void Add( double x, double y )
+ {
+ Add( x, y, PointPair.Missing, null );
+ }
+
+ /// <summary>
+ /// Add a set of values onto the head of the queue,
+ /// overwriting old values if the buffer is full.
+ /// </summary>
+ /// <remarks>
+ /// This method is much more efficient that the <see cref="Add(PointPair)">Add(PointPair)</see>
+ /// method, since it does not require that a new PointPair instance be provided.
+ /// If the buffer already contains a <see cref="PointPair"/> at the head position,
+ /// then the x, y, z, and tag values will be copied into the existing PointPair.
+ /// Otherwise, a new PointPair instance must be created.
+ /// In this way, each PointPair position in the rolling list will only be allocated one time.
+ /// To truly be memory efficient, the <see cref="Remove" />, <see cref="RemoveAt" />,
+ /// and <see cref="Pop" /> methods should be avoided. Also, the <paramref name="tag"/> property
+ /// for this method should be null, since it is a reference type.
+ /// </remarks>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="tag">The Tag value for the PointPair</param>
+ public void Add( double x, double y, object tag )
+ {
+ Add( x, y, PointPair.Missing, tag );
+ }
+
+ /// <summary>
+ /// Add a set of values onto the head of the queue,
+ /// overwriting old values if the buffer is full.
+ /// </summary>
+ /// <remarks>
+ /// This method is much more efficient that the <see cref="Add(PointPair)">Add(PointPair)</see>
+ /// method, since it does not require that a new PointPair instance be provided.
+ /// If the buffer already contains a <see cref="PointPair"/> at the head position,
+ /// then the x, y, z, and tag values will be copied into the existing PointPair.
+ /// Otherwise, a new PointPair instance must be created.
+ /// In this way, each PointPair position in the rolling list will only be allocated one time.
+ /// To truly be memory efficient, the <see cref="Remove" />, <see cref="RemoveAt" />,
+ /// and <see cref="Pop" /> methods should be avoided.
+ /// </remarks>
+ /// <param name="x">The X value</param>
+ /// <param name="y">The Y value</param>
+ /// <param name="z">The Z value</param>
+ public void Add( double x, double y, double z )
+ {
+ Add( x, y, z, null );
+ }
+
+ /// <summary>
+ /// Add a set of points to the <see cref="RollingPointPairList"/>
+ /// from two arrays of type double.
+ /// If either array is null, then a set of ordinal values is automatically
+ /// generated in its place (see <see cref="AxisType.Ordinal"/>).
+ /// If the arrays are of different size, then the larger array prevails and the
+ /// smaller array is padded with <see cref="PointPairBase.Missing"/> values.
+ /// </summary>
+ /// <param name="x">A double[] array of X values</param>
+ /// <param name="y">A double[] array of Y values</param>
+ public void Add( double[] x, double[] y )
+ {
+ int len = 0;
+
+ if ( x != null )
+ len = x.Length;
+ if ( y != null && y.Length > len )
+ len = y.Length;
+
+ for ( int i = 0; i < len; i++ )
+ {
+ PointPair point = new PointPair( 0, 0, 0 );
+ if ( x == null )
+ point.X = (double)i + 1.0;
+ else if ( i < x.Length )
+ point.X = x[i];
+ else
+ point.X = PointPair.Missing;
+
+ if ( y == null )
+ point.Y = (double)i + 1.0;
+ else if ( i < y.Length )
+ point.Y = y[i];
+ else
+ point.Y = PointPair.Missing;
+
+ Add( point );
+ }
+ }
+
+ /// <summary>
+ /// Add a set of points to the <see cref="RollingPointPairList"/> from
+ /// three arrays of type double.
+ /// If the X or Y array is null, then a set of ordinal values is automatically
+ /// generated in its place (see <see cref="AxisType.Ordinal"/>.
+ /// If the <see paramref="z"/> value
+ /// is null, then it is set to zero.
+ /// If the arrays are of different size, then the larger array prevails and the
+ /// smaller array is padded with <see cref="PointPairBase.Missing"/> values.
+ /// </summary>
+ /// <param name="x">A double[] array of X values</param>
+ /// <param name="y">A double[] array of Y values</param>
+ /// <param name="z">A double[] array of Z values</param>
+ public void Add( double[] x, double[] y, double[] z )
+ {
+ int len = 0;
+
+ if ( x != null )
+ len = x.Length;
+ if ( y != null && y.Length > len )
+ len = y.Length;
+ if ( z != null && z.Length > len )
+ len = z.Length;
+
+ for ( int i = 0; i < len; i++ )
+ {
+ PointPair point = new PointPair();
+
+ if ( x == null )
+ point.X = (double)i + 1.0;
+ else if ( i < x.Length )
+ point.X = x[i];
+ else
+ point.X = PointPair.Missing;
+
+ if ( y == null )
+ point.Y = (double)i + 1.0;
+ else if ( i < y.Length )
+ point.Y = y[i];
+ else
+ point.Y = PointPair.Missing;
+
+ if ( z == null )
+ point.Z = (double)i + 1.0;
+ else if ( i < z.Length )
+ point.Z = z[i];
+ else
+ point.Z = PointPair.Missing;
+
+ Add( point );
+ }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected RollingPointPairList( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _headIdx = info.GetInt32( "headIdx" );
+ _tailIdx = info.GetInt32( "tailIdx" );
+ _mBuffer = (PointPair[])info.GetValue( "mBuffer", typeof( PointPair[] ) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "headIdx", _headIdx );
+ info.AddValue( "tailIdx", _tailIdx );
+ info.AddValue( "mBuffer", _mBuffer );
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/SampleMultiPointList.cs b/ZedGraph/SampleMultiPointList.cs
new file mode 100644
index 0000000..dae77ad
--- /dev/null
+++ b/ZedGraph/SampleMultiPointList.cs
@@ -0,0 +1,284 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Charting Library for .Net
+//Copyright � 2005 John Champion and Jerry Vos
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An enum used to specify the X or Y data type of interest -- see
+ /// <see cref="SampleMultiPointList.XData" /> and <see cref="SampleMultiPointList.YData" />.
+ /// </summary>
+ public enum PerfDataType
+ {
+ /// <summary>
+ /// The time (seconds) at which these data are measured
+ /// </summary>
+ Time,
+ /// <summary>
+ /// The distance traveled, meters
+ /// </summary>
+ Distance,
+ /// <summary>
+ /// The instantaneous velocity, meters per second
+ /// </summary>
+ Velocity,
+ /// <summary>
+ /// The instantaneous acceleration, meters per second squared
+ /// </summary>
+ Acceleration
+ };
+
+ /// <summary>
+ /// Sample data structure containing a variety of data values, in this case the values
+ /// are related in that they correspond to the same time value.
+ /// </summary>
+ public class PerformanceData
+ {
+ /// <summary>
+ /// The time (seconds) at which these data are measured
+ /// </summary>
+ public double time;
+ /// <summary>
+ /// The distance traveled, meters
+ /// </summary>
+ public double distance;
+ /// <summary>
+ /// The instantaneous velocity, meters per second
+ /// </summary>
+ public double velocity;
+ /// <summary>
+ /// The instantaneous acceleration, meters per second squared
+ /// </summary>
+ public double acceleration;
+
+ /// <summary>
+ /// Constructor that specifies each data value in the PerformanceData struct
+ /// </summary>
+ /// <param name="time">The time (seconds) at which these data are measured</param>
+ /// <param name="distance">The distance traveled, meters</param>
+ /// <param name="velocity">The instantaneous velocity, meters per second</param>
+ /// <param name="acceleration">The instantaneous acceleration, meters per second squared</param>
+ public PerformanceData( double time, double distance, double velocity, double acceleration )
+ {
+ this.time = time;
+ this.distance = distance;
+ this.velocity = velocity;
+ this.acceleration = acceleration;
+ }
+
+ /// <summary>
+ /// Gets or sets the data value as specified by the <see cref="PerfDataType" /> enum
+ /// </summary>
+ /// <param name="type">The required data value type</param>
+ public double this[ PerfDataType type ]
+ {
+ get
+ {
+ switch( type )
+ {
+ default:
+ case PerfDataType.Time:
+ return time;
+ case PerfDataType.Distance:
+ return distance;
+ case PerfDataType.Velocity:
+ return velocity;
+ case PerfDataType.Acceleration:
+ return acceleration;
+ }
+ }
+ set
+ {
+ switch( type )
+ {
+ case PerfDataType.Time:
+ time = value;
+ break;
+ case PerfDataType.Distance:
+ distance = value;
+ break;
+ case PerfDataType.Velocity:
+ velocity = value;
+ break;
+ case PerfDataType.Acceleration:
+ acceleration = value;
+ break;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// A sample class that holds an internal collection, and implements the
+ /// <see cref="IPointList" /> interface so that it can be used by ZedGraph as curve data.
+ /// </summary>
+ /// <remarks>
+ /// This particular class efficiently implements the data storage so that the class
+ /// can be cloned without duplicating the data points. For example, you can create
+ /// a <see cref="SampleMultiPointList" />, populate it with values, and set
+ /// <see cref="XData" /> = <see cref="PerfDataType.Time" /> and
+ /// <see cref="YData" /> = <see cref="PerfDataType.Distance" />.
+ /// You can then clone this <see cref="SampleMultiPointList" /> to a new one, and set
+ /// <see cref="YData" /> = <see cref="PerfDataType.Velocity" />.
+ /// Each of these <see cref="SampleMultiPointList" />'s can then be used as an
+ /// <see cref="ZedGraph.GraphPane.AddCurve(string,IPointList,Color)" /> argument,
+ /// thereby plotting a distance vs time curve and a velocity vs time curve. There
+ /// will still be only one copy of the data in memory.
+ /// </remarks>
+ [Serializable]
+ public class SampleMultiPointList : IPointList
+ {
+ /// <summary>
+ /// This is where the data are stored. Duplicating the <see cref="SampleMultiPointList" />
+ /// copies the reference to this <see cref="ArrayList" />, but does not actually duplicate
+ /// the data.
+ /// </summary>
+ private ArrayList DataCollection;
+
+ /// <summary>
+ /// Determines what X data will be returned by the indexer of this list.
+ /// </summary>
+ public PerfDataType XData;
+ /// <summary>
+ /// Determines what Y data will be returned by the indexer of this list.
+ /// </summary>
+ public PerfDataType YData;
+
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ public SampleMultiPointList()
+ {
+ XData = PerfDataType.Time;
+ YData = PerfDataType.Distance;
+ DataCollection = new ArrayList();
+ }
+
+ /// <summary>
+ /// The Copy Constructor. This method does NOT duplicate the data, it merely makes
+ /// another "Window" into the same collection. You can make multiple copies and
+ /// set the <see cref="XData" /> and/or <see cref="YData" /> properties to different
+ /// values to plot different data, while maintaining only one copy of the original values.
+ /// </summary>
+ /// <param name="rhs">The <see cref="SampleMultiPointList" /> from which to copy</param>
+ public SampleMultiPointList( SampleMultiPointList rhs )
+ {
+ DataCollection = rhs.DataCollection;
+ XData = rhs.XData;
+ YData = rhs.YData;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public SampleMultiPointList Clone()
+ {
+ return new SampleMultiPointList( this );
+ }
+
+ /// <summary>
+ /// Indexer to access the data. This gets the appropriate data and converts to
+ /// the <see cref="PointPair" /> struct that is compatible with ZedGraph. The
+ /// actual data returned depends on the values of <see cref="XData" /> and
+ /// <see cref="YData" />.
+ /// </summary>
+ /// <param name="index">The ordinal position of the desired point in the list</param>
+ /// <returns>A <see cref="PointPair" /> corresponding to the specified ordinal data position</returns>
+ public PointPair this[ int index ]
+ {
+ get
+ {
+ double xVal, yVal;
+ if ( index >= 0 && index < this.Count )
+ {
+ // grab the specified PerformanceData struct
+ PerformanceData perfData = (PerformanceData) DataCollection[index];
+ // extract the values from the struct according to the user-set
+ // enum values of XData and YData
+ xVal = perfData[XData];
+ yVal = perfData[YData];
+ }
+ else
+ {
+ xVal = PointPair.Missing;
+ yVal = PointPair.Missing;
+ }
+
+ // insert the values into a pointpair and return
+ return new PointPair( xVal, yVal, PointPair.Missing, null );
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of data points in the collection
+ /// </summary>
+ public int Count
+ {
+ get { return DataCollection.Count; }
+ }
+
+ /// <summary>
+ /// Adds the specified <see cref="PerformanceData" /> struct to the end of the collection.
+ /// </summary>
+ /// <param name="perfData">A <see cref="PerformanceData" /> struct to be added</param>
+ /// <returns>The ordinal position in the collection where the values were added</returns>
+ public int Add( PerformanceData perfData )
+ {
+ return DataCollection.Add( perfData );
+ }
+
+ /// <summary>
+ /// Remove the <see cref="PerformanceData" /> struct from the list at the specified
+ /// ordinal location.
+ /// </summary>
+ /// <param name="index">The ordinal location of the <see cref="PerformanceData" />
+ /// struct to be removed</param>
+ public void RemoveAt( int index )
+ {
+ DataCollection.RemoveAt( index );
+ }
+
+ /// <summary>
+ /// Insert the specified <see cref="PerformanceData" /> struct into the list at
+ /// the specified ordinal location.
+ /// </summary>
+ /// <param name="index">The ordinal location at which to insert</param>
+ /// <param name="perfData">The <see cref="PerformanceData" /> struct to be inserted</param>
+ public void Insert( int index, PerformanceData perfData )
+ {
+ DataCollection.Insert( index, perfData );
+ }
+
+ }
+}
diff --git a/ZedGraph/SamplePointList.cs b/ZedGraph/SamplePointList.cs
new file mode 100644
index 0000000..811d65c
--- /dev/null
+++ b/ZedGraph/SamplePointList.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections;
+using System.Text;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// enumeration used to indicate which type of data will be plotted.
+ /// </summary>
+ public enum SampleType
+ {
+ /// <summary>
+ /// Designates the "Time" property will be used
+ /// </summary>
+ Time,
+ /// <summary>
+ /// Designates the "Position" property will be used
+ /// </summary>
+ Position,
+ /// <summary>
+ /// Designates the Instantaneous Velocity property will be used
+ /// </summary>
+ VelocityInst,
+ /// <summary>
+ /// Designates the "Time since start" property will be used
+ /// </summary>
+ TimeDiff,
+ /// <summary>
+ /// Designates the Average Velocity property will be used
+ /// </summary>
+ VelocityAvg
+ };
+
+ /// <summary>
+ /// A simple storage class to maintain an individual sampling of data
+ /// </summary>
+ public class Sample : System.Object
+ {
+ private DateTime _time;
+ private double _position;
+ private double _velocity;
+
+ /// <summary>
+ /// The time of the sample
+ /// </summary>
+ public DateTime Time
+ {
+ get { return _time; }
+ set { _time = value; }
+ }
+ /// <summary>
+ /// The position at sample time
+ /// </summary>
+ public double Position
+ {
+ get { return _position; }
+ set { _position = value; }
+ }
+ /// <summary>
+ /// The instantaneous velocity at sample time
+ /// </summary>
+ public double Velocity
+ {
+ get { return _velocity; }
+ set { _velocity = value; }
+ }
+ }
+
+ /// <summary>
+ /// A collection class to maintain a set of samples
+ /// </summary>
+ [Serializable]
+ public class SamplePointList : IPointList
+ {
+ /// <summary>
+ /// Determines what data type gets plotted for the X values
+ /// </summary>
+ public SampleType XType;
+ /// <summary>
+ /// Determines what data type gets plotted for the Y values
+ /// </summary>
+ public SampleType YType;
+
+ // Stores the collection of samples
+ private ArrayList list;
+
+ /// <summary>
+ /// Indexer: get the Sample instance at the specified ordinal position in the list
+ /// </summary>
+ /// <param name="index">The ordinal position in the list of samples</param>
+ /// <returns>Returns a <see cref="PointPair" /> instance containing the
+ /// data specified by <see cref="XType" /> and <see cref="YType" />
+ /// </returns>
+ public PointPair this[int index]
+ {
+ get
+ {
+ PointPair pt = new PointPair();
+ Sample sample = (Sample) list[index];
+ pt.X = GetValue( sample, XType );
+ pt.Y = GetValue( sample, YType );
+ return pt;
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of samples in the collection
+ /// </summary>
+ public int Count
+ {
+ get { return list.Count; }
+ }
+
+ /// <summary>
+ /// Get the specified data type from the specified sample
+ /// </summary>
+ /// <param name="sample">The sample instance of interest</param>
+ /// <param name="type">The data type to be extracted from the sample</param>
+ /// <returns>A double value representing the requested data</returns>
+ public double GetValue( Sample sample, SampleType type )
+ {
+ switch ( type )
+ {
+ case SampleType.Position:
+ return sample.Position;
+ case SampleType.Time:
+ return sample.Time.ToOADate();
+ case SampleType.TimeDiff:
+ return sample.Time.ToOADate() - ( (Sample)list[0] ).Time.ToOADate();
+ case SampleType.VelocityAvg:
+ double timeDiff = sample.Time.ToOADate() - ( (Sample)list[0] ).Time.ToOADate();
+ if ( timeDiff <= 0 )
+ return PointPair.Missing;
+ else
+ return ( sample.Position - ( (Sample)list[0] ).Position ) / timeDiff;
+ case SampleType.VelocityInst:
+ return sample.Velocity;
+ default:
+ return PointPair.Missing;
+ }
+ }
+
+ /// <summary>
+ /// Append a sample to the collection
+ /// </summary>
+ /// <param name="sample">The sample to append</param>
+ /// <returns>The ordinal position at which the sample was added</returns>
+ public int Add( Sample sample )
+ {
+ return list.Add( sample );
+ }
+
+ // generic Clone: just call the typesafe version
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// typesafe clone method
+ /// </summary>
+ /// <returns>A new cloned SamplePointList. This returns a copy of the structure,
+ /// but it does not duplicate the data (it just keeps a reference to the original)
+ /// </returns>
+ public SamplePointList Clone()
+ {
+ return new SamplePointList( this );
+ }
+
+ /// <summary>
+ /// default constructor
+ /// </summary>
+ public SamplePointList()
+ {
+ XType = SampleType.Time;
+ YType = SampleType.Position;
+ list = new ArrayList();
+ }
+
+ /// <summary>
+ /// copy constructor -- this returns a copy of the structure,
+ /// but it does not duplicate the data (it just keeps a reference to the original)
+ /// </summary>
+ /// <param name="rhs">The SamplePointList to be copied</param>
+ public SamplePointList( SamplePointList rhs )
+ {
+ XType = rhs.XType;
+ YType = rhs.YType;
+
+ // Don't duplicate the data values, just copy the reference to the ArrayList
+ this.list = rhs.list;
+
+ //foreach ( Sample sample in rhs )
+ // list.Add( sample );
+ }
+
+ }
+}
diff --git a/ZedGraph/Scale.cs b/ZedGraph/Scale.cs
new file mode 100644
index 0000000..329c5b1
--- /dev/null
+++ b/ZedGraph/Scale.cs
@@ -0,0 +1,2929 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The Scale class is an abstract base class that encompasses the properties
+ /// and methods associated with a scale of data.
+ /// </summary>
+ /// <remarks>This class is inherited by the
+ /// <see cref="LinearScale"/>, <see cref="LogScale"/>, <see cref="OrdinalScale"/>,
+ /// <see cref="TextScale"/>, <see cref="DateScale"/>, <see cref="ExponentScale"/>,
+ /// <see cref="DateAsOrdinalScale"/>, and <see cref="LinearAsOrdinalScale"/>
+ /// classes to define specific characteristics for those types.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.33 $ $Date: 2007-09-19 06:41:56 $ </version>
+ [Serializable]
+ abstract public class Scale : ISerializable
+ {
+ #region Fields
+
+ /// <summary> Private fields for the <see cref="Axis"/> scale definitions.
+ /// Use the public properties <see cref="Min"/>, <see cref="Max"/>,
+ /// <see cref="MajorStep"/>, <see cref="MinorStep"/>, and <see cref="Exponent" />
+ /// for access to these values.
+ /// </summary>
+ internal double _min,
+ _max,
+ _majorStep,
+ _minorStep,
+ _exponent,
+ _baseTic;
+
+ /// <summary> Private fields for the <see cref="Axis"/> automatic scaling modes.
+ /// Use the public properties <see cref="MinAuto"/>, <see cref="MaxAuto"/>,
+ /// <see cref="MajorStepAuto"/>, <see cref="MinorStepAuto"/>,
+ /// <see cref="MagAuto"/> and <see cref="FormatAuto"/>
+ /// for access to these values.
+ /// </summary>
+ internal bool _minAuto,
+ _maxAuto,
+ _majorStepAuto,
+ _minorStepAuto,
+ _magAuto,
+ _formatAuto;
+
+ /// <summary> Private fields for the <see cref="Axis"/> "grace" settings.
+ /// These values determine how much extra space is left before the first data value
+ /// and after the last data value.
+ /// Use the public properties <see cref="MinGrace"/> and <see cref="MaxGrace"/>
+ /// for access to these values.
+ /// </summary>
+ internal double _minGrace,
+ _maxGrace;
+
+
+ /// <summary> Private field for the <see cref="Axis"/> scale value display.
+ /// Use the public property <see cref="Mag"/> for access to this value.
+ /// </summary>
+ internal int _mag;
+
+ /// <summary> Private fields for the <see cref="Scale"/> attributes.
+ /// Use the public properties <see cref="Scale.IsReverse"/> and <see cref="Scale.IsUseTenPower"/>
+ /// for access to these values.
+ /// </summary>
+ internal bool _isReverse,
+ _isPreventLabelOverlap,
+ _isUseTenPower,
+ _isLabelsInside,
+ _isSkipFirstLabel,
+ _isSkipLastLabel,
+ _isSkipCrossLabel,
+ _isVisible;
+
+ /// <summary> Private <see cref="System.Collections.ArrayList"/> field for the <see cref="Axis"/> array of text labels.
+ /// This property is only used if <see cref="Type"/> is set to
+ /// <see cref="AxisType.Text"/> </summary>
+ internal string[] _textLabels = null;
+
+ /// <summary> Private field for the format of the <see cref="Axis"/> tic labels.
+ /// Use the public property <see cref="Format"/> for access to this value. </summary>
+ /// <seealso cref="FormatAuto"/>
+ internal string _format;
+
+ /// <summary>
+ /// Private fields for Unit types to be used for the major and minor tics.
+ /// See <see cref="MajorUnit"/> and <see cref="MinorUnit"/> for the corresponding
+ /// public properties.
+ /// These types only apply for date-time scales (<see cref="IsDate"/>).
+ /// </summary>
+ /// <value>The value of these types is of enumeration type <see cref="DateUnit"/>
+ /// </value>
+ internal DateUnit _majorUnit,
+ _minorUnit;
+
+ /// <summary> Private field for the alignment of the <see cref="Axis"/> tic labels.
+ /// This fields controls whether the inside, center, or outside edges of the text labels are aligned.
+ /// Use the public property <see cref="Scale.Align"/>
+ /// for access to this value. </summary>
+ /// <seealso cref="FormatAuto"/>
+ internal AlignP _align;
+
+ /// <summary> Private field for the alignment of the <see cref="Axis"/> tic labels.
+ /// This fields controls whether the left, center, or right edges of the text labels are aligned.
+ /// Use the public property <see cref="Scale.AlignH"/>
+ /// for access to this value. </summary>
+ /// <seealso cref="FormatAuto"/>
+ internal AlignH _alignH;
+
+
+ /// <summary> Private fields for the <see cref="Axis"/> font specificatios.
+ /// Use the public properties <see cref="FontSpec"/> and
+ /// <see cref="Scale.FontSpec"/> for access to these values. </summary>
+ internal FontSpec _fontSpec;
+
+ /// <summary>
+ /// Internal field that stores the amount of space between the scale labels and the
+ /// major tics. Use the public property <see cref="LabelGap" /> to access this
+ /// value.
+ /// </summary>
+ internal float _labelGap;
+
+ /// <summary>
+ /// Data range temporary values, used by GetRange().
+ /// </summary>
+ internal double _rangeMin,
+ _rangeMax,
+ _lBound,
+ _uBound;
+
+ /// <summary>
+ /// Pixel positions at the minimum and maximum value for this scale.
+ /// These are temporary values used/valid only during the Draw process.
+ /// </summary>
+ internal float _minPix,
+ _maxPix;
+
+ /// <summary>
+ /// Scale values for calculating transforms. These are temporary values
+ /// used ONLY during the Draw process.
+ /// </summary>
+ /// <remarks>
+ /// These values are just <see cref="Scale.Min" /> and <see cref="Scale.Max" />
+ /// for normal linear scales, but for log or exponent scales they will be a
+ /// linear representation. For <see cref="LogScale" />, it is the
+ /// <see cref="Math.Log(double)" /> of the value, and for <see cref="ExponentScale" />,
+ /// it is the <see cref="Math.Exp(double)" />
+ /// of the value.
+ /// </remarks>
+ internal double _minLinTemp,
+ _maxLinTemp;
+
+ /// <summary>
+ /// Gets or sets the linearized version of the <see cref="Min" /> scale range.
+ /// </summary>
+ /// <remarks>
+ /// This value is valid at any time, whereas <see cref="_minLinTemp" /> is an optimization
+ /// pre-set that is only valid during draw operations.
+ /// </remarks>
+ internal double _minLinearized
+ {
+ get { return Linearize( _min ); }
+ set { _min = DeLinearize( value ); }
+ }
+
+ /// <summary>
+ /// Gets or sets the linearized version of the <see cref="Max" /> scale range.
+ /// </summary>
+ /// <remarks>
+ /// This value is valid at any time, whereas <see cref="_maxLinTemp" /> is an optimization
+ /// pre-set that is only valid during draw operations.
+ /// </remarks>
+ internal double _maxLinearized
+ {
+ get { return Linearize( _max ); }
+ set { _max = DeLinearize( value ); }
+ }
+
+ /// <summary>
+ /// private field that stores the owner Axis that contains this Scale instance.
+ /// </summary>
+ internal Axis _ownerAxis;
+
+ #endregion
+
+ #region Defaults
+
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="Scale"/> class.
+ /// </summary>
+ public struct Default
+ {
+ /// <summary>
+ /// The default "zero lever" for automatically selecting the axis
+ /// scale range (see <see cref="PickScale"/>). This number is
+ /// used to determine when an axis scale range should be extended to
+ /// include the zero value. This value is maintained only in the
+ /// <see cref="Default"/> class, and cannot be changed after compilation.
+ /// </summary>
+ public static double ZeroLever = 0.25;
+ /// <summary> The default "grace" value applied to the minimum data range.
+ /// This value is
+ /// expressed as a fraction of the total data range. For example, assume the data
+ /// range is from 4.0 to 16.0, leaving a range of 12.0. If MinGrace is set to
+ /// 0.1, then 10% of the range, or 1.2 will be subtracted from the minimum data value.
+ /// The scale will then be ranged to cover at least 2.8 to 16.0.
+ /// </summary>
+ /// <seealso cref="MinGrace"/>
+ public static double MinGrace = 0.1;
+ /// <summary> The default "grace" value applied to the maximum data range.
+ /// This value is
+ /// expressed as a fraction of the total data range. For example, assume the data
+ /// range is from 4.0 to 16.0, leaving a range of 12.0. If MaxGrace is set to
+ /// 0.1, then 10% of the range, or 1.2 will be added to the maximum data value.
+ /// The scale will then be ranged to cover at least 4.0 to 17.2.
+ /// </summary>
+ /// <seealso cref="MinGrace"/>
+ /// <seealso cref="MaxGrace"/>
+ public static double MaxGrace = 0.1;
+ /// <summary>
+ /// The maximum number of text labels (major tics) that will be allowed on the plot by
+ /// the automatic scaling logic. This value applies only to <see cref="AxisType.Text"/>
+ /// axes. If there are more than MaxTextLabels on the plot, then
+ /// <see cref="MajorStep"/> will be increased to reduce the number of labels. That is,
+ /// the step size might be increased to 2.0 to show only every other label.
+ /// </summary>
+ public static double MaxTextLabels = 12.0;
+ /// <summary>
+ /// The default target number of steps for automatically selecting the X axis
+ /// scale step size (see <see cref="PickScale"/>).
+ /// This number is an initial target value for the number of major steps
+ /// on an axis. This value is maintained only in the
+ /// <see cref="Default"/> class, and cannot be changed after compilation.
+ /// </summary>
+ public static double TargetXSteps = 7.0;
+ /// <summary>
+ /// The default target number of steps for automatically selecting the Y or Y2 axis
+ /// scale step size (see <see cref="PickScale"/>).
+ /// This number is an initial target value for the number of major steps
+ /// on an axis. This value is maintained only in the
+ /// <see cref="Default"/> class, and cannot be changed after compilation.
+ /// </summary>
+ public static double TargetYSteps = 7.0;
+ /// <summary>
+ /// The default target number of minor steps for automatically selecting the X axis
+ /// scale minor step size (see <see cref="PickScale"/>).
+ /// This number is an initial target value for the number of minor steps
+ /// on an axis. This value is maintained only in the
+ /// <see cref="Default"/> class, and cannot be changed after compilation.
+ /// </summary>
+ public static double TargetMinorXSteps = 5.0;
+ /// <summary>
+ /// The default target number of minor steps for automatically selecting the Y or Y2 axis
+ /// scale minor step size (see <see cref="PickScale"/>).
+ /// This number is an initial target value for the number of minor steps
+ /// on an axis. This value is maintained only in the
+ /// <see cref="Default"/> class, and cannot be changed after compilation.
+ /// </summary>
+ public static double TargetMinorYSteps = 5.0;
+ /// <summary>
+ /// The default reverse mode for the <see cref="Axis"/> scale
+ /// (<see cref="IsReverse"/> property). true for a reversed scale
+ /// (X decreasing to the left, Y/Y2 decreasing upwards), false otherwise.
+ /// </summary>
+ public static bool IsReverse = false;
+ /// <summary>
+ /// The default setting for the <see cref="Axis"/> scale format string
+ /// (<see cref="Format"/> property). For numeric values, this value is
+ /// setting according to the <see cref="String.Format(string,object)"/> format strings. For date
+ /// type values, this value is set as per the <see cref="XDate.ToString()"/> function.
+ /// </summary>
+ //public static string ScaleFormat = "&dd-&mmm-&yy &hh:&nn";
+ public static string Format = "g";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Year"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Year"/>.
+ /// This value normally defaults to 1825 days (5 years).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeYearYear = 1825; // 5 years
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Year"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Month"/>.
+ /// This value normally defaults to 730 days (2 years).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeYearMonth = 730; // 2 years
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Month"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Month"/>.
+ /// This value normally defaults to 300 days (10 months).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeMonthMonth = 300; // 10 months
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Day"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Day"/>.
+ /// This value normally defaults to 10 days.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeDayDay = 10; // 10 days
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Day"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Hour"/>.
+ /// This value normally defaults to 3 days.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeDayHour = 3; // 3 days
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Hour"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Hour"/>.
+ /// This value normally defaults to 0.4167 days (10 hours).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeHourHour = 0.4167; // 10 hours
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Hour"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Minute"/>.
+ /// This value normally defaults to 0.125 days (3 hours).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeHourMinute = 0.125; // 3 hours
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Minute"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Minute"/>.
+ /// This value normally defaults to 6.94e-3 days (10 minutes).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeMinuteMinute = 6.94e-3; // 10 Minutes
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Minute"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Second"/>.
+ /// This value normally defaults to 2.083e-3 days (3 minutes).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeMinuteSecond = 2.083e-3; // 3 Minutes
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// If the total span of data exceeds this number (in days), then the auto-range
+ /// code will select <see cref="MajorUnit"/> = <see cref="DateUnit.Second"/>
+ /// and <see cref="MinorUnit"/> = <see cref="DateUnit.Second"/>.
+ /// This value normally defaults to 3.472e-5 days (3 seconds).
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ public static double RangeSecondSecond = 3.472e-5; // 3 Seconds
+
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Year"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Year"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatYearYear = "yyyy";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Year"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Month"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatYearMonth = "MMM-yyyy";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Month"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Month"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatMonthMonth = "MMM-yyyy";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Day"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Day"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatDayDay = "d-MMM";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Day"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Hour"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatDayHour = "d-MMM HH:mm";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Hour"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Hour"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatHourHour = "HH:mm";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Hour"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Minute"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatHourMinute = "HH:mm";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Minute"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Minute"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatMinuteMinute = "HH:mm";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Minute"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Second"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatMinuteSecond = "mm:ss";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Second"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Second"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatSecondSecond = "mm:ss";
+ /// <summary>
+ /// A default setting for the <see cref="AxisType.Date"/> auto-ranging code.
+ /// This values applies only to Date-Time type axes.
+ /// This is the format used for the scale values when auto-ranging code
+ /// selects a <see cref="Format"/> of <see cref="DateUnit.Millisecond"/>
+ /// for <see cref="MajorUnit"/> and <see cref="DateUnit.Millisecond"/> for
+ /// for <see cref="MinorUnit"/>.
+ /// This value is used by the <see cref="DateScale.CalcDateStepSize(double,double,Scale)"/> method.
+ /// </summary>
+ /// <seealso cref="System.Globalization.DateTimeFormatInfo"/>
+ public static string FormatMillisecond = "ss.fff";
+
+ /* Prior format assignments using original XDate.ToString()
+ this.scaleFormat = "&yyyy";
+ this.scaleFormat = "&mmm-&yy";
+ this.scaleFormat = "&mmm-&yy";
+ scaleFormat = "&d-&mmm";
+ this.scaleFormat = "&d-&mmm &hh:&nn";
+ scaleFormat = "&hh:&nn";
+ scaleFormat = "&hh:&nn";
+ scaleFormat = "&hh:&nn";
+ scaleFormat = "&nn:&ss";
+ scaleFormat = "&nn:&ss";
+ */
+ /// <summary> The default alignment of the <see cref="Axis"/> tic labels.
+ /// This value controls whether the inside, center, or outside edges of the text labels are aligned.
+ /// </summary>
+ /// <seealso cref="AlignP"/>
+ public static AlignP Align = AlignP.Center;
+ /// <summary> The default alignment of the <see cref="Axis"/> tic labels.
+ /// This value controls whether the left, center, or right edges of the text labels are aligned.
+ /// </summary>
+ /// <seealso cref="AlignH"/>
+ public static AlignH AlignH = AlignH.Center;
+ /// <summary>
+ /// The default font family for the <see cref="Axis"/> scale values
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.FontSpec.Family"/> property).
+ /// </summary>
+ public static string FontFamily = "Arial";
+ /// <summary>
+ /// The default font size for the <see cref="Axis"/> scale values
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.FontSpec.Size"/> property). Units are
+ /// in points (1/72 inch).
+ /// </summary>
+ public static float FontSize = 14;
+ /// <summary>
+ /// The default font color for the <see cref="Axis"/> scale values
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.FontSpec.FontColor"/> property).
+ /// </summary>
+ public static Color FontColor = Color.Black;
+ /// <summary>
+ /// The default font bold mode for the <see cref="Axis"/> scale values
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.FontSpec.IsBold"/> property). true
+ /// for a bold typeface, false otherwise.
+ /// </summary>
+ public static bool FontBold = false;
+ /// <summary>
+ /// The default font italic mode for the <see cref="Axis"/> scale values
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.FontSpec.IsItalic"/> property). true
+ /// for an italic typeface, false otherwise.
+ /// </summary>
+ public static bool FontItalic = false;
+ /// <summary>
+ /// The default font underline mode for the <see cref="Axis"/> scale values
+ /// font specification <see cref="FontSpec"/>
+ /// (<see cref="ZedGraph.FontSpec.IsUnderline"/> property). true
+ /// for an underlined typeface, false otherwise.
+ /// </summary>
+ public static bool FontUnderline = false;
+ /// <summary>
+ /// The default color for filling in the scale text background
+ /// (see <see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.White;
+ /// <summary>
+ /// The default custom brush for filling in the scale text background
+ /// (see <see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null;
+ /// <summary>
+ /// The default fill mode for filling in the scale text background
+ /// (see <see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FillType = FillType.None;
+ /// <summary>
+ /// The default value for <see cref="IsVisible"/>, which determines
+ /// whether or not the scale values are displayed.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// The default value for <see cref="IsLabelsInside"/>, which determines
+ /// whether or not the scale labels and title for the <see cref="Axis"/> will appear
+ /// on the opposite side of the <see cref="Axis"/> that it normally appears.
+ /// </summary>
+ public static bool IsLabelsInside = false;
+ /// <summary>
+ /// Determines the size of the band at the beginning and end of the axis that will have labels
+ /// omitted if the axis is shifted due to a non-default location using the <see cref="Axis.Cross"/>
+ /// property.
+ /// </summary>
+ /// <remarks>
+ /// This parameter applies only when <see cref="Axis.CrossAuto"/> is false. It is scaled according
+ /// to the size of the graph based on <see cref="PaneBase.BaseDimension"/>. When a non-default
+ /// axis location is selected, the first and last labels on that axis will overlap the opposing
+ /// axis frame. This parameter allows those labels to be omitted to avoid the overlap. Set this
+ /// parameter to zero to turn off the effect.
+ /// </remarks>
+ public static float EdgeTolerance = 6;
+
+ /// <summary>
+ /// The default setting for the gap between the outside tics (or the axis edge
+ /// if there are no outside tics) and the scale labels, expressed as a fraction of
+ /// the major tic size.
+ /// </summary>
+ public static float LabelGap = 0.3f;
+ }
+
+ #endregion
+
+ #region constructors
+
+ /// <summary>
+ /// Basic constructor -- requires that the <see cref="Scale" /> object be intialized with
+ /// a pre-existing owner <see cref="Axis" />.
+ /// </summary>
+ /// <param name="ownerAxis">The <see cref="Axis" /> object that is the owner of this
+ /// <see cref="Scale" /> instance.</param>
+ public Scale( Axis ownerAxis )
+ {
+ _ownerAxis = ownerAxis;
+
+ _min = 0.0;
+ _max = 1.0;
+ _majorStep = 0.1;
+ _minorStep = 0.1;
+ _exponent = 1.0;
+ _mag = 0;
+ _baseTic = PointPair.Missing;
+
+ _minGrace = Default.MinGrace;
+ _maxGrace = Default.MaxGrace;
+
+ _minAuto = true;
+ _maxAuto = true;
+ _majorStepAuto = true;
+ _minorStepAuto = true;
+ _magAuto = true;
+ _formatAuto = true;
+
+ _isReverse = Default.IsReverse;
+ _isUseTenPower = true;
+ _isPreventLabelOverlap = true;
+ _isVisible = true;
+ _isSkipFirstLabel = false;
+ _isSkipLastLabel = false;
+ _isSkipCrossLabel = false;
+
+ _majorUnit = DateUnit.Day;
+ _minorUnit = DateUnit.Day;
+
+ _format = null;
+ _textLabels = null;
+
+ _isLabelsInside = Default.IsLabelsInside;
+ _align = Default.Align;
+ _alignH = Default.AlignH;
+
+ _fontSpec = new FontSpec(
+ Default.FontFamily, Default.FontSize,
+ Default.FontColor, Default.FontBold,
+ Default.FontUnderline, Default.FontItalic,
+ Default.FillColor, Default.FillBrush,
+ Default.FillType );
+
+ _fontSpec.Border.IsVisible = false;
+ _labelGap = Default.LabelGap;
+ }
+
+ /// <summary>
+ /// Copy Constructor. Create a new <see cref="Scale" /> object based on the specified
+ /// existing one.
+ /// </summary>
+ /// <param name="rhs">The <see cref="Scale" /> object to be copied.</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="Scale" /></param>
+ public Scale( Scale rhs, Axis owner )
+ {
+ _ownerAxis = owner;
+
+ _min = rhs._min;
+ _max = rhs._max;
+ _majorStep = rhs._majorStep;
+ _minorStep = rhs._minorStep;
+ _exponent = rhs._exponent;
+ _baseTic = rhs._baseTic;
+
+ _minAuto = rhs._minAuto;
+ _maxAuto = rhs._maxAuto;
+ _majorStepAuto = rhs._majorStepAuto;
+ _minorStepAuto = rhs._minorStepAuto;
+ _magAuto = rhs._magAuto;
+ _formatAuto = rhs._formatAuto;
+
+ _minGrace = rhs._minGrace;
+ _maxGrace = rhs._maxGrace;
+
+ _mag = rhs._mag;
+
+ _isUseTenPower = rhs._isUseTenPower;
+ _isReverse = rhs._isReverse;
+ _isPreventLabelOverlap = rhs._isPreventLabelOverlap;
+ _isVisible = rhs._isVisible;
+ _isSkipFirstLabel = rhs._isSkipFirstLabel;
+ _isSkipLastLabel = rhs._isSkipLastLabel;
+ _isSkipCrossLabel = rhs._isSkipCrossLabel;
+
+ _majorUnit = rhs._majorUnit;
+ _minorUnit = rhs._minorUnit;
+
+ _format = rhs._format;
+
+ _isLabelsInside = rhs._isLabelsInside;
+ _align = rhs._align;
+ _alignH = rhs._alignH;
+
+ _fontSpec = (FontSpec) rhs._fontSpec.Clone();
+
+ _labelGap = rhs._labelGap;
+
+ if ( rhs._textLabels != null )
+ _textLabels = (string[])rhs._textLabels.Clone();
+ else
+ _textLabels = null;
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ abstract public Scale Clone( Axis owner );
+/*
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of Clone />
+ /// </summary>
+ /// <remarks>
+ /// Note that this method must be called with an explicit cast to ICloneable, and
+ /// that it is inherently virtual. For example:
+ /// <code>
+ /// ParentClass foo = new ChildClass();
+ /// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
+ /// </code>
+ /// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
+ /// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
+ /// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
+ /// </remarks>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
+ //return new PaneBase( this );
+ }
+*/
+
+ /// <summary>
+ /// A construction method that creates a new <see cref="Scale"/> object using the
+ /// properties of an existing <see cref="Scale"/> object, but specifying a new
+ /// <see cref="AxisType"/>.
+ /// </summary>
+ /// <remarks>
+ /// This constructor is used to change the type of an existing <see cref="Axis" />.
+ /// By specifying the old <see cref="Scale"/> object, you are giving a set of properties
+ /// (which encompasses all fields associated with the scale, since the derived types
+ /// have no fields) to be used in creating a new <see cref="Scale"/> object, only this
+ /// time having the newly specified object type.</remarks>
+ /// <param name="oldScale">The existing <see cref="Scale" /> object from which to
+ /// copy the field data.</param>
+ /// <param name="type">An <see cref="AxisType"/> representing the type of derived type
+ /// of new <see cref="Scale" /> object to create.</param>
+ /// <returns>The new <see cref="Scale"/> object.</returns>
+ public Scale MakeNewScale( Scale oldScale, AxisType type )
+ {
+ switch ( type )
+ {
+ case AxisType.Linear:
+ return new LinearScale( oldScale, _ownerAxis );
+ case AxisType.Date:
+ return new DateScale( oldScale, _ownerAxis );
+ case AxisType.Log:
+ return new LogScale( oldScale, _ownerAxis );
+ case AxisType.Exponent:
+ return new ExponentScale( oldScale, _ownerAxis );
+ case AxisType.Ordinal:
+ return new OrdinalScale( oldScale, _ownerAxis );
+ case AxisType.Text:
+ return new TextScale( oldScale, _ownerAxis );
+ case AxisType.DateAsOrdinal:
+ return new DateAsOrdinalScale( oldScale, _ownerAxis );
+ case AxisType.LinearAsOrdinal:
+ return new LinearAsOrdinalScale( oldScale, _ownerAxis );
+ default:
+ throw new Exception( "Implementation Error: Invalid AxisType" );
+ }
+ }
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ // schema changed to 2 with isScaleVisible
+ public const int schema = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Scale( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _min = info.GetDouble( "min" );
+ _max = info.GetDouble( "max" );
+ _majorStep = info.GetDouble( "majorStep" );
+ _minorStep = info.GetDouble( "minorStep" );
+ _exponent = info.GetDouble( "exponent" );
+ _baseTic = info.GetDouble( "baseTic" );
+
+
+ _minAuto = info.GetBoolean( "minAuto" );
+ _maxAuto = info.GetBoolean( "maxAuto" );
+ _majorStepAuto = info.GetBoolean( "majorStepAuto" );
+ _minorStepAuto = info.GetBoolean( "minorStepAuto" );
+ _magAuto = info.GetBoolean( "magAuto" );
+ _formatAuto = info.GetBoolean( "formatAuto" );
+
+ _minGrace = info.GetDouble( "minGrace" );
+ _maxGrace = info.GetDouble( "maxGrace" );
+
+ _mag = info.GetInt32( "mag" );
+
+ _isReverse = info.GetBoolean( "isReverse" );
+ _isPreventLabelOverlap = info.GetBoolean( "isPreventLabelOverlap" );
+ _isUseTenPower = info.GetBoolean( "isUseTenPower" );
+
+ _isVisible = true;
+ _isVisible = info.GetBoolean( "isVisible" );
+
+ _isSkipFirstLabel = info.GetBoolean( "isSkipFirstLabel" );
+ _isSkipLastLabel = info.GetBoolean( "isSkipLastLabel" );
+ _isSkipCrossLabel = info.GetBoolean( "isSkipCrossLabel" );
+
+ _textLabels = (string[]) info.GetValue( "textLabels", typeof(string[]) );
+ _format = info.GetString( "format" );
+
+ _majorUnit = (DateUnit) info.GetValue( "majorUnit", typeof(DateUnit) );
+ _minorUnit = (DateUnit) info.GetValue( "minorUnit", typeof(DateUnit) );
+
+ _isLabelsInside = info.GetBoolean( "isLabelsInside" );
+ _align = (AlignP)info.GetValue( "align", typeof( AlignP ) );
+ if ( schema >= 11 )
+ _alignH = (AlignH)info.GetValue( "alignH", typeof( AlignH ) );
+
+ _fontSpec = (FontSpec)info.GetValue( "fontSpec", typeof( FontSpec ) );
+ _labelGap = info.GetSingle( "labelGap" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to
+ /// serialize the target object
+ /// </summary>
+ /// <remarks>
+ /// You MUST set the _ownerAxis property after deserializing a BarSettings object.
+ /// </remarks>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "min", _min );
+ info.AddValue( "max", _max );
+ info.AddValue( "majorStep", _majorStep );
+ info.AddValue( "minorStep", _minorStep );
+ info.AddValue( "exponent", _exponent );
+ info.AddValue( "baseTic", _baseTic );
+
+ info.AddValue( "minAuto", _minAuto );
+ info.AddValue( "maxAuto", _maxAuto );
+ info.AddValue( "majorStepAuto", _majorStepAuto );
+ info.AddValue( "minorStepAuto", _minorStepAuto );
+ info.AddValue( "magAuto", _magAuto );
+ info.AddValue( "formatAuto", _formatAuto );
+
+ info.AddValue( "minGrace", _minGrace );
+ info.AddValue( "maxGrace", _maxGrace );
+
+ info.AddValue( "mag", _mag );
+ info.AddValue( "isReverse", _isReverse );
+ info.AddValue( "isPreventLabelOverlap", _isPreventLabelOverlap );
+ info.AddValue( "isUseTenPower", _isUseTenPower );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "isSkipFirstLabel", _isSkipFirstLabel );
+ info.AddValue( "isSkipLastLabel", _isSkipLastLabel );
+ info.AddValue( "isSkipCrossLabel", _isSkipCrossLabel );
+
+
+ info.AddValue( "textLabels", _textLabels );
+ info.AddValue( "format", _format );
+
+ info.AddValue( "majorUnit", _majorUnit );
+ info.AddValue( "minorUnit", _minorUnit );
+
+ info.AddValue( "isLabelsInside", _isLabelsInside );
+ info.AddValue( "align", _align );
+ info.AddValue( "alignH", _alignH );
+ info.AddValue( "fontSpec", _fontSpec );
+ info.AddValue( "labelGap", _labelGap );
+ }
+ #endregion
+
+ #region properties
+
+ /// <summary>
+ /// Get an <see cref="AxisType" /> enumeration that indicates the type of this scale.
+ /// </summary>
+ abstract public AxisType Type { get; }
+
+ /// <summary>
+ /// True if this scale is <see cref="AxisType.Log" />, false otherwise.
+ /// </summary>
+ public bool IsLog { get { return this is LogScale; } }
+ /// <summary>
+ /// True if this scale is <see cref="AxisType.Exponent" />, false otherwise.
+ /// </summary>
+ public bool IsExponent { get { return this is ExponentScale; } }
+ /// <summary>
+ /// True if this scale is <see cref="AxisType.Date" />, false otherwise.
+ /// </summary>
+ public bool IsDate { get { return this is DateScale; } }
+ /// <summary>
+ /// True if this scale is <see cref="AxisType.Text" />, false otherwise.
+ /// </summary>
+ public bool IsText { get { return this is TextScale; } }
+ /// <summary>
+ /// True if this scale is <see cref="AxisType.Ordinal" />, false otherwise.
+ /// </summary>
+ /// <remarks>
+ /// Note that this is only true for an actual <see cref="OrdinalScale" /> class.
+ /// This property will be false for other ordinal types such as
+ /// <see cref="AxisType.Text" />, <see cref="AxisType.LinearAsOrdinal" />,
+ /// or <see cref="AxisType.DateAsOrdinal" />. Use the <see cref="IsAnyOrdinal" />
+ /// as a "catchall" for all ordinal type axes.
+ /// </remarks>
+ public bool IsOrdinal { get { return this is OrdinalScale; } }
+
+ /// <summary>
+ /// Gets a value that indicates if this <see cref="Scale" /> is of any of the
+ /// ordinal types in the <see cref="AxisType" /> enumeration.
+ /// </summary>
+ /// <seealso cref="Type" />
+ public bool IsAnyOrdinal
+ {
+ get
+ {
+ AxisType type = this.Type;
+
+ return type == AxisType.Ordinal ||
+ type == AxisType.Text ||
+ type == AxisType.LinearAsOrdinal ||
+ type == AxisType.DateAsOrdinal;
+ }
+ }
+/*
+ /// <summary>
+ /// The pixel position at the minimum value for this axis. This read-only
+ /// value is used/valid only during the Draw process.
+ /// </summary>
+ public float MinPix
+ {
+ get { return _minPix; }
+ }
+ /// <summary>
+ /// The pixel position at the maximum value for this axis. This read-only
+ /// value is used/valid only during the Draw process.
+ /// </summary>
+ public float MaxPix
+ {
+ get { return _maxPix; }
+ }
+*/
+ /// <summary>
+ /// Gets or sets the minimum scale value for this <see cref="Scale" />.
+ /// </summary>
+ /// <remarks>This value can be set
+ /// automatically based on the state of <see cref="MinAuto"/>. If
+ /// this value is set manually, then <see cref="MinAuto"/> will
+ /// also be set to false.
+ /// </remarks>
+ /// <value> The value is defined in user scale units for <see cref="AxisType.Log"/>
+ /// and <see cref="AxisType.Linear"/> axes. For <see cref="AxisType.Text"/>
+ /// and <see cref="AxisType.Ordinal"/> axes,
+ /// this value is an ordinal starting with 1.0. For <see cref="AxisType.Date"/>
+ /// axes, this value is in XL Date format (see <see cref="XDate"/>, which is the
+ /// number of days since the reference date of January 1, 1900.</value>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MajorStep"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="MinAuto"/>
+ public virtual double Min
+ {
+ get { return _min; }
+ set { _min = value; _minAuto = false; }
+ }
+ /// <summary>
+ /// Gets or sets the maximum scale value for this <see cref="Scale" />.
+ /// </summary>
+ /// <remarks>
+ /// This value can be set
+ /// automatically based on the state of <see cref="MaxAuto"/>. If
+ /// this value is set manually, then <see cref="MaxAuto"/> will
+ /// also be set to false.
+ /// </remarks>
+ /// <value> The value is defined in user scale units for <see cref="AxisType.Log"/>
+ /// and <see cref="AxisType.Linear"/> axes. For <see cref="AxisType.Text"/>
+ /// and <see cref="AxisType.Ordinal"/> axes,
+ /// this value is an ordinal starting with 1.0. For <see cref="AxisType.Date"/>
+ /// axes, this value is in XL Date format (see <see cref="XDate"/>, which is the
+ /// number of days since the reference date of January 1, 1900.</value>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="MajorStep"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="MaxAuto"/>
+ public virtual double Max
+ {
+ get { return _max; }
+ set { _max = value; _maxAuto = false; }
+ }
+ /// <summary>
+ /// Gets or sets the scale step size for this <see cref="Scale" /> (the increment between
+ /// labeled axis values).
+ /// </summary>
+ /// <remarks>
+ /// This value can be set
+ /// automatically based on the state of <see cref="MajorStepAuto"/>. If
+ /// this value is set manually, then <see cref="MajorStepAuto"/> will
+ /// also be set to false. This value is ignored for <see cref="AxisType.Log"/>
+ /// axes. For <see cref="AxisType.Date"/> axes, this
+ /// value is defined in units of <see cref="MajorUnit"/>.
+ /// </remarks>
+ /// <value> The value is defined in user scale units </value>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="MajorStepAuto"/>
+ /// <seealso cref="ZedGraph.Scale.Default.TargetXSteps"/>
+ /// <seealso cref="ZedGraph.Scale.Default.TargetYSteps"/>
+ /// <seealso cref="ZedGraph.Scale.Default.ZeroLever"/>
+ /// <seealso cref="ZedGraph.Scale.Default.MaxTextLabels"/>
+ public double MajorStep
+ {
+ get { return _majorStep; }
+ set
+ {
+ if ( value < 1e-300 )
+ {
+ _majorStepAuto = true;
+ }
+ else
+ {
+ _majorStep = value;
+ _majorStepAuto = false;
+ }
+ }
+ }
+ /// <summary>
+ /// Gets or sets the scale minor step size for this <see cref="Scale" /> (the spacing between
+ /// minor tics).
+ /// </summary>
+ /// <remarks>This value can be set
+ /// automatically based on the state of <see cref="MinorStepAuto"/>. If
+ /// this value is set manually, then <see cref="MinorStepAuto"/> will
+ /// also be set to false. This value is ignored for <see cref="AxisType.Log"/> and
+ /// <see cref="AxisType.Text"/> axes. For <see cref="AxisType.Date"/> axes, this
+ /// value is defined in units of <see cref="MinorUnit"/>.
+ /// </remarks>
+ /// <value> The value is defined in user scale units </value>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MajorStep"/>
+ /// <seealso cref="MinorStepAuto"/>
+ public double MinorStep
+ {
+ get { return _minorStep; }
+ set
+ {
+ if ( value < 1e-300 )
+ {
+ _minorStepAuto = true;
+ }
+ else
+ {
+ _minorStep = value;
+ _minorStepAuto = false;
+ }
+ }
+ }
+ /// <summary>
+ /// Gets or sets the scale exponent value. This only applies to <see cref="AxisType.Exponent" />.
+ /// </summary>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="MajorStepAuto"/>
+ /// <seealso cref="ZedGraph.Scale.Default.TargetXSteps"/>
+ /// <seealso cref="ZedGraph.Scale.Default.TargetYSteps"/>
+ /// <seealso cref="ZedGraph.Scale.Default.ZeroLever"/>
+ /// <seealso cref="ZedGraph.Scale.Default.MaxTextLabels"/>
+ public double Exponent
+ {
+ get { return _exponent; }
+ set { _exponent = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the scale value at which the first major tic label will appear.
+ /// </summary>
+ /// <remarks>This property allows the scale labels to start at an irregular value.
+ /// For example, on a scale range with <see cref="Min"/> = 0, <see cref="Max"/> = 1000,
+ /// and <see cref="MajorStep"/> = 200, a <see cref="BaseTic"/> value of 50 would cause
+ /// the scale labels to appear at values 50, 250, 450, 650, and 850. Note that the
+ /// default value for this property is <see cref="PointPairBase.Missing"/>, which means the
+ /// value is not used. Setting this property to any value other than
+ /// <see cref="PointPairBase.Missing"/> will activate the effect. The value specified must
+ /// coincide with the first major tic. That is, if <see cref="BaseTic"/> were set to
+ /// 650 in the example above, then the major tics would only occur at 650 and 850. This
+ /// setting may affect the minor tics, since the minor tics are always referenced to the
+ /// <see cref="BaseTic"/>. That is, in the example above, if the <see cref="MinorStep"/>
+ /// were set to 30 (making it a non-multiple of the major step), then the minor tics would
+ /// occur at 20, 50 (so it lines up with the BaseTic), 80, 110, 140, etc.
+ /// </remarks>
+ /// <value> The value is defined in user scale units </value>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MajorStep"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="Axis.Cross"/>
+ public double BaseTic
+ {
+ get { return _baseTic; }
+ set { _baseTic = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the type of units used for the major step size (<see cref="MajorStep"/>).
+ /// </summary>
+ /// <remarks>
+ /// This unit type only applies to Date-Time axes (<see cref="AxisType.Date"/> = true).
+ /// The axis is set to date type with the <see cref="Type"/> property.
+ /// The unit types are defined as <see cref="DateUnit"/>.
+ /// </remarks>
+ /// <value> The value is a <see cref="DateUnit"/> enum type </value>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MajorStep"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="MajorStepAuto"/>
+ public DateUnit MajorUnit
+ {
+ get { return _majorUnit; }
+ set { _majorUnit = value; }
+ }
+ /// <summary>
+ /// Gets or sets the type of units used for the minor step size (<see cref="MinorStep"/>).
+ /// </summary>
+ /// <remarks>
+ /// This unit type only applies to Date-Time axes (<see cref="AxisType.Date"/> = true).
+ /// The axis is set to date type with the <see cref="Type"/> property.
+ /// The unit types are defined as <see cref="DateUnit"/>.
+ /// </remarks>
+ /// <value> The value is a <see cref="DateUnit"/> enum type </value>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="MajorStep"/>
+ /// <seealso cref="MinorStep"/>
+ /// <seealso cref="MinorStepAuto"/>
+ public DateUnit MinorUnit
+ {
+ get { return _minorUnit; }
+ set { _minorUnit = value; }
+ }
+
+ /// <summary>
+ /// Gets the major unit multiplier for this scale type, if any.
+ /// </summary>
+ /// <remarks>The major unit multiplier will correct the units of
+ /// <see cref="MajorStep" /> to match the units of <see cref="Min" />
+ /// and <see cref="Max" />. This reflects the setting of
+ /// <see cref="MajorUnit" />.
+ /// </remarks>
+ virtual internal double MajorUnitMultiplier
+ {
+ get { return 1.0; }
+ }
+
+ /// <summary>
+ /// Gets the minor unit multiplier for this scale type, if any.
+ /// </summary>
+ /// <remarks>The minor unit multiplier will correct the units of
+ /// <see cref="MinorStep" /> to match the units of <see cref="Min" />
+ /// and <see cref="Max" />. This reflects the setting of
+ /// <see cref="MinorUnit" />.
+ /// </remarks>
+ virtual internal double MinorUnitMultiplier
+ {
+ get { return 1.0; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the minimum scale value <see cref="Min"/>
+ /// is set automatically.
+ /// </summary>
+ /// <remarks>
+ /// This value will be set to false if
+ /// <see cref="Min"/> is manually changed.
+ /// </remarks>
+ /// <value>true for automatic mode, false for manual mode</value>
+ /// <seealso cref="Min"/>
+ public bool MinAuto
+ {
+ get { return _minAuto; }
+ set { _minAuto = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the maximum scale value <see cref="Max"/>
+ /// is set automatically.
+ /// </summary>
+ /// <remarks>
+ /// This value will be set to false if
+ /// <see cref="Max"/> is manually changed.
+ /// </remarks>
+ /// <value>true for automatic mode, false for manual mode</value>
+ /// <seealso cref="Max"/>
+ public bool MaxAuto
+ {
+ get { return _maxAuto; }
+ set { _maxAuto = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the scale step size <see cref="MajorStep"/>
+ /// is set automatically.
+ /// </summary>
+ /// <remarks>
+ /// This value will be set to false if
+ /// <see cref="MajorStep"/> is manually changed.
+ /// </remarks>
+ /// <value>true for automatic mode, false for manual mode</value>
+ /// <seealso cref="MajorStep"/>
+ public bool MajorStepAuto
+ {
+ get { return _majorStepAuto; }
+ set { _majorStepAuto = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the minor scale step size <see cref="MinorStep"/>
+ /// is set automatically.
+ /// </summary>
+ /// <remarks>
+ /// This value will be set to false if
+ /// <see cref="MinorStep"/> is manually changed.
+ /// </remarks>
+ /// <value>true for automatic mode, false for manual mode</value>
+ /// <seealso cref="MinorStep"/>
+ public bool MinorStepAuto
+ {
+ get { return _minorStepAuto; }
+ set { _minorStepAuto = value; }
+ }
+
+ /// <summary>
+ /// Determines whether or not the scale label format <see cref="Format"/>
+ /// is determined automatically based on the range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This value will be set to false if
+ /// <see cref="Format"/> is manually changed.
+ /// </remarks>
+ /// <value>true if <see cref="Format"/> will be set automatically, false
+ /// if it is to be set manually by the user</value>
+ /// <seealso cref="Mag"/>
+ /// <seealso cref="Format"/>
+ /// <seealso cref="FontSpec"/>
+ public bool FormatAuto
+ {
+ get { return _formatAuto; }
+ set { _formatAuto = value; }
+ }
+
+ /// <summary>
+ /// The format of the <see cref="Axis"/> tic labels.
+ /// </summary>
+ /// <remarks>
+ /// This property may be a date format or a numeric format, depending on the setting of
+ /// <see cref="Type">Scale.Type</see>.
+ /// This property may be set automatically by ZedGraph, depending on the state of
+ /// <see cref="FormatAuto"/>.
+ /// </remarks>
+ /// <value>The format string conforms to the
+ /// <see cref="System.Globalization.DateTimeFormatInfo" /> for date formats, and
+ /// <see cref="System.Globalization.NumberFormatInfo" /> for numeric formats.
+ /// </value>
+ /// <seealso cref="Mag"/>
+ /// <seealso cref="FormatAuto"/>
+ /// <seealso cref="FontSpec"/>
+ // /// <seealso cref="NumDec"/>
+ public string Format
+ {
+ get { return _format; }
+ set { _format = value; _formatAuto = false; }
+ }
+
+ /// <summary>
+ /// The magnitude multiplier for scale values.
+ /// </summary>
+ /// <remarks>
+ /// This is used to limit
+ /// the size of the displayed value labels. For example, if the value
+ /// is really 2000000, then the graph will display 2000 with a 10^3
+ /// magnitude multiplier. This value can be determined automatically
+ /// depending on the state of <see cref="MagAuto"/>.
+ /// If this value is set manually by the user,
+ /// then <see cref="MagAuto"/> will also be set to false.
+ /// </remarks>
+ /// <value>The magnitude multiplier (power of 10) for the scale
+ /// value labels</value>
+ /// <seealso cref="AxisLabel.IsOmitMag"/>
+ /// <seealso cref="Axis.Title"/>
+ /// <seealso cref="Format"/>
+ /// <seealso cref="FontSpec"/>
+ // /// <seealso cref="NumDec"/>
+ public int Mag
+ {
+ get { return _mag; }
+ set { _mag = value; _magAuto = false; }
+ }
+ /// <summary>
+ /// Determines whether the <see cref="Mag"/> value will be set
+ /// automatically based on the data, or manually by the user.
+ /// </summary>
+ /// <remarks>
+ /// If the user manually sets the <see cref="Mag"/> value, then this
+ /// flag will be set to false.
+ /// </remarks>
+ /// <value>true to have <see cref="Mag"/> set automatically,
+ /// false otherwise</value>
+ /// <seealso cref="AxisLabel.IsOmitMag"/>
+ /// <seealso cref="Axis.Title"/>
+ /// <seealso cref="Mag"/>
+ public bool MagAuto
+ {
+ get { return _magAuto; }
+ set { _magAuto = value; }
+ }
+
+ /// <summary> Gets or sets the "grace" value applied to the minimum data range.
+ /// </summary>
+ /// <remarks>
+ /// This value is
+ /// expressed as a fraction of the total data range. For example, assume the data
+ /// range is from 4.0 to 16.0, leaving a range of 12.0. If MinGrace is set to
+ /// 0.1, then 10% of the range, or 1.2 will be subtracted from the minimum data value.
+ /// The scale will then be ranged to cover at least 2.8 to 16.0.
+ /// </remarks>
+ /// <seealso cref="Min"/>
+ /// <seealso cref="ZedGraph.Scale.Default.MinGrace"/>
+ /// <seealso cref="MaxGrace"/>
+ public double MinGrace
+ {
+ get { return _minGrace; }
+ set { _minGrace = value; }
+ }
+ /// <summary> Gets or sets the "grace" value applied to the maximum data range.
+ /// </summary>
+ /// <remarks>
+ /// This values determines how much extra space is left after the last data value.
+ /// This value is
+ /// expressed as a fraction of the total data range. For example, assume the data
+ /// range is from 4.0 to 16.0, leaving a range of 12.0. If MaxGrace is set to
+ /// 0.1, then 10% of the range, or 1.2 will be added to the maximum data value.
+ /// The scale will then be ranged to cover at least 4.0 to 17.2.
+ /// </remarks>
+ /// <seealso cref="Max"/>
+ /// <seealso cref="ZedGraph.Scale.Default.MaxGrace"/>
+ /// <seealso cref="MinGrace"/>
+ public double MaxGrace
+ {
+ get { return _maxGrace; }
+ set { _maxGrace = value; }
+ }
+
+ /// <summary> Controls the alignment of the <see cref="Axis"/> tic labels.
+ /// </summary>
+ /// <remarks>
+ /// This property controls whether the inside, center, or outside edges of the
+ /// text labels are aligned.
+ /// </remarks>
+ public AlignP Align
+ {
+ get { return _align; }
+ set { _align = value; }
+ }
+
+ /// <summary> Controls the alignment of the <see cref="Axis"/> tic labels.
+ /// </summary>
+ /// <remarks>
+ /// This property controls whether the left, center, or right edges of the
+ /// text labels are aligned.
+ /// </remarks>
+ public AlignH AlignH
+ {
+ get { return _alignH; }
+ set { _alignH = value; }
+ }
+
+ /// <summary>
+ /// Gets a reference to the <see cref="ZedGraph.FontSpec"/> class used to render
+ /// the scale values
+ /// </summary>
+ /// <seealso cref="Default.FontFamily"/>
+ /// <seealso cref="Default.FontSize"/>
+ /// <seealso cref="Default.FontColor"/>
+ /// <seealso cref="Default.FontBold"/>
+ /// <seealso cref="Default.FontUnderline"/>
+ /// <seealso cref="Default.FontItalic"/>
+ public FontSpec FontSpec
+ {
+ get { return _fontSpec; }
+ set
+ {
+ if ( value == null )
+ throw new ArgumentNullException( "Uninitialized FontSpec in Scale" );
+ _fontSpec = value;
+ }
+ }
+
+ /// <summary>
+ /// The gap between the scale labels and the tics.
+ /// </summary>
+ public float LabelGap
+ {
+ get { return _labelGap; }
+ set { _labelGap = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that causes the axis scale labels and title to appear on the
+ /// opposite side of the axis.
+ /// </summary>
+ /// <remarks>
+ /// For example, setting this flag to true for the <see cref="YAxis"/> will shift the
+ /// axis labels and title to the right side of the <see cref="YAxis"/> instead of the
+ /// normal left-side location. Set this property to true for the <see cref="XAxis" />,
+ /// and set the <see cref="Axis.Cross"/> property for the <see cref="XAxis"/> to an arbitrarily
+ /// large value (assuming <see cref="IsReverse"/> is false for the <see cref="YAxis" />) in
+ /// order to have the <see cref="XAxis"/> appear at the top of the <see cref="Chart.Rect" />.
+ /// </remarks>
+ /// <seealso cref="IsReverse"/>
+ /// <seealso cref="Axis.Cross"/>
+ public bool IsLabelsInside
+ {
+ get { return _isLabelsInside; }
+ set { _isLabelsInside = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that causes the first scale label for this <see cref="Axis"/> to be
+ /// hidden.
+ /// </summary>
+ /// <remarks>
+ /// Often, for axis that have an active <see cref="Axis.Cross"/> setting (e.g., <see cref="Axis.CrossAuto"/>
+ /// is false), the first and/or last scale label are overlapped by opposing axes. Use this
+ /// property to hide the first scale label to avoid the overlap. Note that setting this value
+ /// to true will hide any scale label that appears within <see cref="Scale.Default.EdgeTolerance"/> of the
+ /// beginning of the <see cref="Axis"/>.
+ /// </remarks>
+ public bool IsSkipFirstLabel
+ {
+ get { return _isSkipFirstLabel; }
+ set { _isSkipFirstLabel = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that causes the last scale label for this <see cref="Axis"/> to be
+ /// hidden.
+ /// </summary>
+ /// <remarks>
+ /// Often, for axis that have an active <see cref="Axis.Cross"/> setting (e.g., <see cref="Axis.CrossAuto"/>
+ /// is false), the first and/or last scale label are overlapped by opposing axes. Use this
+ /// property to hide the last scale label to avoid the overlap. Note that setting this value
+ /// to true will hide any scale label that appears within <see cref="Scale.Default.EdgeTolerance"/> of the
+ /// end of the <see cref="Axis"/>.
+ /// </remarks>
+ public bool IsSkipLastLabel
+ {
+ get { return _isSkipLastLabel; }
+ set { _isSkipLastLabel = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that causes the scale label that is located at the <see cref="Axis.Cross" />
+ /// value for this <see cref="Axis"/> to be hidden.
+ /// </summary>
+ /// <remarks>
+ /// For axes that have an active <see cref="Axis.Cross"/> setting (e.g., <see cref="Axis.CrossAuto"/>
+ /// is false), the scale label at the <see cref="Axis.Cross" /> value is overlapped by opposing axes.
+ /// Use this property to hide the scale label to avoid the overlap.
+ /// </remarks>
+ public bool IsSkipCrossLabel
+ {
+ get { return _isSkipCrossLabel; }
+ set { _isSkipCrossLabel = value; }
+ }
+
+ /// <summary>
+ /// Determines if the scale values are reversed for this <see cref="Axis"/>
+ /// </summary>
+ /// <value>true for the X values to decrease to the right or the Y values to
+ /// decrease upwards, false otherwise</value>
+ /// <seealso cref="ZedGraph.Scale.Default.IsReverse"/>.
+ public bool IsReverse
+ {
+ get { return _isReverse; }
+ set { _isReverse = value; }
+ }
+ /// <summary>
+ /// Determines if powers-of-ten notation will be used for the numeric value labels.
+ /// </summary>
+ /// <remarks>
+ /// The powers-of-ten notation is just the text "10" followed by a superscripted value
+ /// indicating the magnitude. This mode is only valid for log scales (see
+ /// <see cref="IsLog"/> and <see cref="Type"/>).
+ /// </remarks>
+ /// <value> boolean value; true to show the title as a power of ten, false to
+ /// show a regular numeric value (e.g., "0.01", "10", "1000")</value>
+ public bool IsUseTenPower
+ {
+ get { return _isUseTenPower; }
+ set { _isUseTenPower = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a <see cref="bool"/> value that determines if ZedGraph will check to
+ /// see if the <see cref="Axis"/> scale labels are close enough to overlap. If so,
+ /// ZedGraph will adjust the step size to prevent overlap.
+ /// </summary>
+ /// <remarks>
+ /// The process of checking for overlap is done during the <see cref="GraphPane.AxisChange()"/>
+ /// method call, and affects the selection of the major step size (<see cref="MajorStep"/>).
+ /// </remarks>
+ /// <value> boolean value; true to check for overlap, false otherwise</value>
+ public bool IsPreventLabelOverlap
+ {
+ get { return _isPreventLabelOverlap; }
+ set { _isPreventLabelOverlap = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines whether or not the scale values will be shown.
+ /// </summary>
+ /// <value>true to show the scale values, false otherwise</value>
+ /// <seealso cref="Axis.IsVisible"/>.
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ /// <summary>
+ /// The text labels for this <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>
+ /// This property is only
+ /// applicable if <see cref="Type"/> is set to <see cref="AxisType.Text"/>.
+ /// </remarks>
+ public string[] TextLabels
+ {
+ get { return _textLabels; }
+ set { _textLabels = value; }
+ }
+
+ #endregion
+/*
+ #region events
+
+ /// <summary>
+ /// A delegate that allows full custom formatting of the Axis labels
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane" /> for which the label is to be
+ /// formatted</param>
+ /// <param name="axis">The <see cref="Axis" /> for which the label is to be formatted</param>
+ /// <param name="val">The value to be formatted</param>
+ /// <param name="index">The zero-based index of the label to be formatted</param>
+ /// <returns>
+ /// A string value representing the label, or null if the ZedGraph should go ahead
+ /// and generate the label according to the current settings</returns>
+ /// <seealso cref="ScaleFormatEvent" />
+ public delegate string ScaleFormatHandler( GraphPane pane, Axis axis, double val, int index );
+
+ /// <summary>
+ /// Subscribe to this event to handle custom formatting of the scale labels.
+ /// </summary>
+ public event ScaleFormatHandler ScaleFormatEvent;
+
+ #endregion
+*/
+ #region Methods
+
+ /// <summary>
+ /// Setup some temporary transform values in preparation for rendering the
+ /// <see cref="Axis"/>.
+ /// </summary>
+ /// <remarks>
+ /// This method is typically called by the parent <see cref="GraphPane"/>
+ /// object as part of the <see cref="GraphPane.Draw"/> method. It is also
+ /// called by <see cref="GraphPane.GeneralTransform(double,double,CoordType)"/> and
+ /// <see cref="GraphPane.ReverseTransform( PointF, out double, out double )"/>
+ /// methods to setup for coordinate transformations.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="axis">
+ /// The parent <see cref="Axis" /> for this <see cref="Scale" />
+ /// </param>
+ virtual public void SetupScaleData( GraphPane pane, Axis axis )
+ {
+ // save the ChartRect data for transforming scale values to pixels
+ if ( axis is XAxis || axis is X2Axis )
+ {
+ _minPix = pane.Chart._rect.Left;
+ _maxPix = pane.Chart._rect.Right;
+ }
+ else
+ {
+ _minPix = pane.Chart._rect.Top;
+ _maxPix = pane.Chart._rect.Bottom;
+ }
+
+ _minLinTemp = Linearize( _min );
+ _maxLinTemp = Linearize( _max );
+
+ }
+
+/* internal void ResetScaleData()
+ {
+ _minPix = float.NaN;
+ _maxPix = float.NaN;
+ _minLinTemp = double.NaN;
+ _maxLinTemp = double.NaN;
+ }
+*/
+ /// <summary>
+ /// Convert a value to its linear equivalent for this type of scale.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to just return the value unchanged. However,
+ /// for <see cref="AxisType.Log" /> and <see cref="AxisType.Exponent" />,
+ /// it returns the log or power equivalent.
+ /// </remarks>
+ /// <param name="val">The value to be converted</param>
+ virtual public double Linearize( double val )
+ {
+ return val;
+ }
+
+ /// <summary>
+ /// Convert a value from its linear equivalent to its actual scale value
+ /// for this type of scale.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to just return the value unchanged. However,
+ /// for <see cref="AxisType.Log" /> and <see cref="AxisType.Exponent" />,
+ /// it returns the anti-log or inverse-power equivalent.
+ /// </remarks>
+ /// <param name="val">The value to be converted</param>
+ virtual public double DeLinearize( double val )
+ {
+ return val;
+ }
+/*
+ /// <summary>
+ /// Make a value label for the axis at the specified ordinal position.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="IsLog"/>, <see cref="IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="IsLog"/>)
+ /// and text (<see cref="IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ virtual internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( this.ScaleFormatEvent != null )
+ {
+ string label;
+
+ label = this.ScaleFormatEvent( pane, _ownerAxis, dVal, index );
+ if ( label != null )
+ return label;
+ }
+
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ // linear or ordinal is the default behavior
+ // this method is overridden for other Scale types
+
+ double scaleMult = Math.Pow( (double) 10.0, _mag );
+
+ return ( dVal / scaleMult ).ToString( _format );
+ }
+*/
+
+ /// <summary>
+ /// Make a value label for the axis at the specified ordinal position.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="IsLog"/>, <see cref="IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="IsLog"/>)
+ /// and text (<see cref="IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ virtual internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ // linear or ordinal is the default behavior
+ // this method is overridden for other Scale types
+
+ double scaleMult = Math.Pow( (double)10.0, _mag );
+
+ return ( dVal / scaleMult ).ToString( _format );
+ }
+
+ /// <summary>
+ /// Get the maximum width of the scale value text that is required to label this
+ /// <see cref="Axis"/>.
+ /// The results of this method are used to determine how much space is required for
+ /// the axis labels.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="applyAngle">
+ /// true to get the bounding box of the text using the <see cref="ZedGraph.FontSpec.Angle" />,
+ /// false to just get the bounding box without rotation
+ /// </param>
+ /// <returns>the maximum width of the text in pixel units</returns>
+ internal SizeF GetScaleMaxSpace( Graphics g, GraphPane pane, float scaleFactor,
+ bool applyAngle )
+ {
+ if ( _isVisible )
+ {
+ double dVal,
+ scaleMult = Math.Pow( (double)10.0, _mag );
+ int i;
+
+ float saveAngle = _fontSpec.Angle;
+ if ( !applyAngle )
+ _fontSpec.Angle = 0;
+
+ int nTics = CalcNumTics();
+
+ double startVal = CalcBaseTic();
+
+ SizeF maxSpace = new SizeF( 0, 0 );
+
+ // Repeat for each tic
+ for ( i = 0; i < nTics; i++ )
+ {
+ dVal = CalcMajorTicValue( startVal, i );
+
+ // draw the label
+ //string tmpStr = MakeLabel( pane, i, dVal );
+ string tmpStr = _ownerAxis.MakeLabelEventWorks( pane, i, dVal );
+
+ SizeF sizeF;
+ if ( this.IsLog && _isUseTenPower )
+ sizeF = _fontSpec.BoundingBoxTenPower( g, tmpStr,
+ scaleFactor );
+ else
+ sizeF = _fontSpec.BoundingBox( g, tmpStr,
+ scaleFactor );
+
+ if ( sizeF.Height > maxSpace.Height )
+ maxSpace.Height = sizeF.Height;
+ if ( sizeF.Width > maxSpace.Width )
+ maxSpace.Width = sizeF.Width;
+ }
+
+ _fontSpec.Angle = saveAngle;
+
+ return maxSpace;
+ }
+ else
+ return new SizeF(0,0);
+ }
+
+ /// <summary>
+ /// Determine the value for any major tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="IsLog"/>, <see cref="IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double)
+ /// </param>
+ /// <param name="tic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified major tic value (floating point double).
+ /// </returns>
+ virtual internal double CalcMajorTicValue( double baseVal, double tic )
+ {
+ // Default behavior is a normal linear scale (also works for ordinal types)
+ return baseVal + (double) _majorStep * tic;
+ }
+
+ /// <summary>
+ /// Determine the value for any minor tic.
+ /// </summary>
+ /// <remarks>
+ /// This method properly accounts for <see cref="IsLog"/>, <see cref="IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <param name="baseVal">
+ /// The value of the first major tic (floating point double). This tic value is the base
+ /// reference for all tics (including minor ones).
+ /// </param>
+ /// <param name="iTic">
+ /// The major tic number (0 = first major tic). For log scales, this is the actual power of 10.
+ /// </param>
+ /// <returns>
+ /// The specified minor tic value (floating point double).
+ /// </returns>
+ virtual internal double CalcMinorTicValue( double baseVal, int iTic )
+ {
+ // default behavior is a linear axis (works for ordinal types too
+ return baseVal + (double) _minorStep * (double) iTic;
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first minor tic mark
+ /// </summary>
+ /// <param name="baseVal">
+ /// The value of the first major tic for the axis.
+ /// </param>
+ /// <returns>
+ /// The ordinal position of the first minor tic, relative to the first major tic.
+ /// This value can be negative (e.g., -3 means the first minor tic is 3 minor step
+ /// increments before the first major tic.
+ /// </returns>
+ virtual internal int CalcMinorStart( double baseVal )
+ {
+ // Default behavior is for a linear scale (works for ordinal as well
+ return (int) ( ( _min - baseVal ) / _minorStep );
+ }
+
+ /// <summary>
+ /// Determine the value for the first major tic.
+ /// </summary>
+ /// <remarks>
+ /// This is done by finding the first possible value that is an integral multiple of
+ /// the step size, taking into account the date/time units if appropriate.
+ /// This method properly accounts for <see cref="IsLog"/>, <see cref="IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <returns>
+ /// First major tic value (floating point double).
+ /// </returns>
+ virtual internal double CalcBaseTic()
+ {
+ if ( _baseTic != PointPair.Missing )
+ return _baseTic;
+ else if ( IsAnyOrdinal )
+ {
+ // basetic is always 1 for ordinal types
+ return 1;
+ }
+ else
+ {
+ // default behavior is linear or ordinal type
+ // go to the nearest even multiple of the step size
+ return Math.Ceiling( (double)_min / (double)_majorStep - 0.00000001 )
+ * (double)_majorStep;
+ }
+ }
+
+ /// <summary>
+ /// Draw the value labels, tic marks, and grid lines as
+ /// required for this <see cref="Axis"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="baseVal">
+ /// The first major tic value for the axis
+ /// </param>
+ /// <param name="nTics">
+ /// The total number of major tics for the axis
+ /// </param>
+ /// <param name="topPix">
+ /// The pixel location of the far side of the ChartRect from this axis.
+ /// This value is the ChartRect.Height for the XAxis, or the ChartRect.Width
+ /// for the YAxis and Y2Axis.
+ /// </param>
+ /// <param name="shift">The number of pixels to shift this axis, based on the
+ /// value of <see cref="Axis.Cross"/>. A positive value is into the ChartRect relative to
+ /// the default axis position.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ internal void DrawLabels( Graphics g, GraphPane pane, double baseVal, int nTics,
+ float topPix, float shift, float scaleFactor )
+ {
+ MajorTic tic = _ownerAxis._majorTic;
+// MajorGrid grid = _ownerAxis._majorGrid;
+
+ double dVal, dVal2;
+ float pixVal, pixVal2;
+ float scaledTic = tic.ScaledTic( scaleFactor );
+
+ double scaleMult = Math.Pow( (double)10.0, _mag );
+
+ using ( Pen ticPen = tic.GetPen( pane, scaleFactor ) )
+// using ( Pen gridPen = grid.GetPen( pane, scaleFactor ) )
+ {
+ // get the Y position of the center of the axis labels
+ // (the axis itself is referenced at zero)
+ SizeF maxLabelSize = GetScaleMaxSpace( g, pane, scaleFactor, true );
+ float charHeight = _fontSpec.GetHeight( scaleFactor );
+ float maxSpace = maxLabelSize.Height;
+
+ float edgeTolerance = Default.EdgeTolerance * scaleFactor;
+ double rangeTol = ( _maxLinTemp - _minLinTemp ) * 0.001;
+
+ int firstTic = (int)( ( _minLinTemp - baseVal ) / _majorStep + 0.99 );
+ if ( firstTic < 0 )
+ firstTic = 0;
+
+ // save the position of the previous tic
+ float lastPixVal = -10000;
+
+ // loop for each major tic
+ for ( int i = firstTic; i < nTics + firstTic; i++ )
+ {
+ dVal = CalcMajorTicValue( baseVal, i );
+
+ // If we're before the start of the scale, just go to the next tic
+ if ( dVal < _minLinTemp )
+ continue;
+ // if we've already past the end of the scale, then we're done
+ if ( dVal > _maxLinTemp + rangeTol )
+ break;
+
+ // convert the value to a pixel position
+ pixVal = LocalTransform( dVal );
+
+ // see if the tic marks will be drawn between the labels instead of at the labels
+ // (this applies only to AxisType.Text
+ if ( tic._isBetweenLabels && IsText )
+ {
+ // We need one extra tic in order to draw the tics between labels
+ // so provide an exception here
+ if ( i == 0 )
+ {
+ dVal2 = CalcMajorTicValue( baseVal, -0.5 );
+ if ( dVal2 >= _minLinTemp )
+ {
+ pixVal2 = LocalTransform( dVal2 );
+ tic.Draw( g, pane, ticPen, pixVal2, topPix, shift, scaledTic );
+
+// grid.Draw( g, gridPen, pixVal2, topPix );
+ }
+ }
+
+ dVal2 = CalcMajorTicValue( baseVal, (double)i + 0.5 );
+ if ( dVal2 > _maxLinTemp )
+ break;
+ pixVal2 = LocalTransform( dVal2 );
+ }
+ else
+ pixVal2 = pixVal;
+
+ tic.Draw( g, pane, ticPen, pixVal2, topPix, shift, scaledTic );
+
+ // draw the grid
+// grid.Draw( g, gridPen, pixVal2, topPix );
+
+ bool isMaxValueAtMaxPix = ( ( _ownerAxis is XAxis || _ownerAxis is Y2Axis ) &&
+ !IsReverse ) ||
+ ( _ownerAxis is Y2Axis && IsReverse );
+
+ bool isSkipZone = ( ( ( _isSkipFirstLabel && isMaxValueAtMaxPix ) ||
+ ( _isSkipLastLabel && !isMaxValueAtMaxPix ) ) &&
+ pixVal < edgeTolerance ) ||
+ ( ( ( _isSkipLastLabel && isMaxValueAtMaxPix ) ||
+ ( _isSkipFirstLabel && !isMaxValueAtMaxPix ) ) &&
+ pixVal > _maxPix - _minPix - edgeTolerance );
+
+ bool isSkipCross = _isSkipCrossLabel && !_ownerAxis._crossAuto &&
+ Math.Abs( _ownerAxis._cross - dVal ) < rangeTol * 10.0;
+
+ isSkipZone = isSkipZone || isSkipCross;
+
+ if ( _isVisible && !isSkipZone )
+ {
+ // For exponential scales, just skip any label that would overlap with the previous one
+ // This is because exponential scales have varying label spacing
+ if ( IsPreventLabelOverlap &&
+ Math.Abs( pixVal - lastPixVal ) < maxLabelSize.Width )
+ continue;
+
+ DrawLabel( g, pane, i, dVal, pixVal, shift, maxSpace, scaledTic, charHeight, scaleFactor );
+
+ lastPixVal = pixVal;
+ }
+ }
+ }
+ }
+
+ internal void DrawGrid( Graphics g, GraphPane pane, double baseVal, float topPix, float scaleFactor )
+ {
+ MajorTic tic = _ownerAxis._majorTic;
+ MajorGrid grid = _ownerAxis._majorGrid;
+
+ int nTics = CalcNumTics();
+
+ double dVal, dVal2;
+ float pixVal, pixVal2;
+
+ using ( Pen gridPen = grid.GetPen( pane, scaleFactor ) )
+ {
+ // get the Y position of the center of the axis labels
+ // (the axis itself is referenced at zero)
+// SizeF maxLabelSize = GetScaleMaxSpace( g, pane, scaleFactor, true );
+// float charHeight = _fontSpec.GetHeight( scaleFactor );
+// float maxSpace = maxLabelSize.Height;
+
+// float edgeTolerance = Default.EdgeTolerance * scaleFactor;
+ double rangeTol = ( _maxLinTemp - _minLinTemp ) * 0.001;
+
+ int firstTic = (int)( ( _minLinTemp - baseVal ) / _majorStep + 0.99 );
+ if ( firstTic < 0 )
+ firstTic = 0;
+
+ // save the position of the previous tic
+// float lastPixVal = -10000;
+
+ // loop for each major tic
+ for ( int i = firstTic; i < nTics + firstTic; i++ )
+ {
+ dVal = CalcMajorTicValue( baseVal, i );
+
+ // If we're before the start of the scale, just go to the next tic
+ if ( dVal < _minLinTemp )
+ continue;
+ // if we've already past the end of the scale, then we're done
+ if ( dVal > _maxLinTemp + rangeTol )
+ break;
+
+ // convert the value to a pixel position
+ pixVal = LocalTransform( dVal );
+
+ // see if the tic marks will be drawn between the labels instead of at the labels
+ // (this applies only to AxisType.Text
+ if ( tic._isBetweenLabels && IsText )
+ {
+ // We need one extra tic in order to draw the tics between labels
+ // so provide an exception here
+ if ( i == 0 )
+ {
+ dVal2 = CalcMajorTicValue( baseVal, -0.5 );
+ if ( dVal2 >= _minLinTemp )
+ {
+ pixVal2 = LocalTransform( dVal2 );
+ grid.Draw( g, gridPen, pixVal2, topPix );
+ }
+ }
+
+ dVal2 = CalcMajorTicValue( baseVal, (double)i + 0.5 );
+ if ( dVal2 > _maxLinTemp )
+ break;
+ pixVal2 = LocalTransform( dVal2 );
+ }
+ else
+ pixVal2 = pixVal;
+
+ // draw the grid
+ grid.Draw( g, gridPen, pixVal2, topPix );
+ }
+ }
+ }
+
+ internal void DrawLabel( Graphics g, GraphPane pane, int i, double dVal, float pixVal,
+ float shift, float maxSpace, float scaledTic, float charHeight, float scaleFactor )
+ {
+ float textTop, textCenter;
+ if ( _ownerAxis.MajorTic.IsOutside )
+ textTop = scaledTic + charHeight * _labelGap;
+ else
+ textTop = charHeight * _labelGap;
+
+ // draw the label
+ //string tmpStr = MakeLabel( pane, i, dVal );
+ string tmpStr = _ownerAxis.MakeLabelEventWorks( pane, i, dVal );
+
+ float height;
+ if ( this.IsLog && _isUseTenPower )
+ height = _fontSpec.BoundingBoxTenPower( g, tmpStr, scaleFactor ).Height;
+ else
+ height = _fontSpec.BoundingBox( g, tmpStr, scaleFactor ).Height;
+
+ if ( _align == AlignP.Center )
+ textCenter = textTop + maxSpace / 2.0F;
+ else if ( _align == AlignP.Outside )
+ textCenter = textTop + maxSpace - height / 2.0F;
+ else // inside
+ textCenter = textTop + height / 2.0F;
+
+ if ( _isLabelsInside )
+ textCenter = shift - textCenter;
+ else
+ textCenter = shift + textCenter;
+
+ AlignV av = AlignV.Center;
+ AlignH ah = AlignH.Center;
+
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ ah = _alignH;
+ else
+ av = _alignH == AlignH.Left ? AlignV.Top : ( _alignH == AlignH.Right ? AlignV.Bottom : AlignV.Center );
+
+ if ( this.IsLog && _isUseTenPower )
+ _fontSpec.DrawTenPower( g, pane, tmpStr,
+ pixVal, textCenter,
+ ah, av,
+ scaleFactor );
+ else
+ _fontSpec.Draw( g, pane, tmpStr,
+ pixVal, textCenter,
+ ah, av,
+ scaleFactor );
+ }
+
+ /// <summary>
+ /// Draw the scale, including the tic marks, value labels, and grid lines as
+ /// required for this <see cref="Axis"/>.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="shiftPos">
+ /// The number of pixels to shift to account for non-primary axis position (e.g.,
+ /// the second, third, fourth, etc. <see cref="YAxis" /> or <see cref="Y2Axis" />.
+ /// </param>
+ internal void Draw( Graphics g, GraphPane pane, float scaleFactor, float shiftPos )
+ {
+ MajorGrid majorGrid = _ownerAxis._majorGrid;
+ MajorTic majorTic = _ownerAxis._majorTic;
+ MinorTic minorTic = _ownerAxis._minorTic;
+
+ float rightPix,
+ topPix;
+
+ GetTopRightPix( pane, out topPix, out rightPix );
+
+ // calculate the total number of major tics required
+ int nTics = CalcNumTics();
+
+ // get the first major tic value
+ double baseVal = CalcBaseTic();
+
+ using ( Pen pen = new Pen( _ownerAxis.Color,
+ pane.ScaledPenWidth( majorTic._penWidth, scaleFactor ) ) )
+ {
+
+ // redraw the axis border
+ if ( _ownerAxis.IsAxisSegmentVisible )
+ g.DrawLine( pen, 0.0F, shiftPos, rightPix, shiftPos );
+
+ // Draw a zero-value line if needed
+ if ( majorGrid._isZeroLine && _min < 0.0 && _max > 0.0 )
+ {
+ float zeroPix = LocalTransform( 0.0 );
+ g.DrawLine( pen, zeroPix, 0.0F, zeroPix, topPix );
+ }
+ }
+
+ // draw the major tics and labels
+ DrawLabels( g, pane, baseVal, nTics, topPix, shiftPos, scaleFactor );
+
+// _ownerAxis.DrawMinorTics( g, pane, baseVal, shiftPos, scaleFactor, topPix );
+
+ _ownerAxis.DrawTitle( g, pane, shiftPos, scaleFactor );
+ }
+
+ internal void GetTopRightPix( GraphPane pane, out float topPix, out float rightPix )
+ {
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ {
+ rightPix = pane.Chart._rect.Width;
+ topPix = -pane.Chart._rect.Height;
+ }
+ else
+ {
+ rightPix = pane.Chart._rect.Height;
+ topPix = -pane.Chart._rect.Width;
+ }
+
+ // sanity check
+ if ( _min >= _max )
+ return;
+
+ // if the step size is outrageous, then quit
+ // (step size not used for log scales)
+ if ( !IsLog )
+ {
+ if ( _majorStep <= 0 || _minorStep <= 0 )
+ return;
+
+ double tMajor = ( _max - _min ) / ( _majorStep * MajorUnitMultiplier );
+ double tMinor = ( _max - _min ) / ( _minorStep * MinorUnitMultiplier );
+
+ MinorTic minorTic = _ownerAxis._minorTic;
+
+ if ( tMajor > 1000 ||
+ ( ( minorTic.IsOutside || minorTic.IsInside || minorTic.IsOpposite )
+ && tMinor > 5000 ) )
+ return;
+ }
+ }
+
+ /// <summary>
+ /// Determine the width, in pixel units, of each bar cluster including
+ /// the cluster gaps and bar gaps.
+ /// </summary>
+ /// <remarks>
+ /// This method uses the <see cref="BarSettings.ClusterScaleWidth" /> for
+ /// non-ordinal axes, or a cluster width of 1.0 for ordinal axes.
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <returns>The width of each bar cluster, in pixel units</returns>
+ public float GetClusterWidth( GraphPane pane )
+ {
+ double basisVal = _min;
+ return Math.Abs( Transform( basisVal +
+ ( IsAnyOrdinal ? 1.0 : pane._barSettings._clusterScaleWidth ) ) -
+ Transform( basisVal ) );
+ }
+
+ /// <summary>
+ /// Calculates the cluster width, in pixels, by transforming the specified
+ /// clusterScaleWidth.
+ /// </summary>
+ /// <param name="clusterScaleWidth">The width in user scale units of each
+ /// bar cluster</param>
+ /// <returns>The equivalent pixel size of the bar cluster</returns>
+ public float GetClusterWidth( double clusterScaleWidth )
+ {
+ double basisVal = _min;
+ return Math.Abs( Transform( basisVal + clusterScaleWidth ) -
+ Transform( basisVal ) );
+ }
+
+ #endregion
+
+ #region Scale Picker Methods
+
+ /// <summary>
+ /// Select a reasonable scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// The scale range is chosen
+ /// based on increments of 1, 2, or 5 (because they are even divisors of 10). This
+ /// routine honors the <see cref="MinAuto"/>, <see cref="MaxAuto"/>,
+ /// and <see cref="MajorStepAuto"/> autorange settings as well as the <see cref="IsLog"/>
+ /// setting. In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Min"/>, <see cref="Max"/>, or <see cref="MajorStep"/>
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values. The basic defaults for
+ /// scale selection are defined using <see cref="Default.ZeroLever"/>,
+ /// <see cref="Default.TargetXSteps"/>, and <see cref="Default.TargetYSteps"/>
+ /// from the <see cref="Default"/> default class.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Min"/> is set to scale minimum (if <see cref="MinAuto"/> = true)</para>
+ /// <para><see cref="Max"/> is set to scale maximum (if <see cref="MaxAuto"/> = true)</para>
+ /// <para><see cref="MajorStep"/> is set to scale step size (if <see cref="MajorStepAuto"/> = true)</para>
+ /// <para><see cref="MinorStep"/> is set to scale minor step size (if <see cref="MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ virtual public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ double minVal = _rangeMin;
+ double maxVal = _rangeMax;
+
+ // Make sure that minVal and maxVal are legitimate values
+ if ( Double.IsInfinity( minVal ) || Double.IsNaN( minVal ) || minVal == Double.MaxValue )
+ minVal = 0.0;
+ if ( Double.IsInfinity( maxVal ) || Double.IsNaN( maxVal ) || maxVal == Double.MaxValue )
+ maxVal = 0.0;
+
+ // if the scales are autoranged, use the actual data values for the range
+ double range = maxVal - minVal;
+
+ // "Grace" is applied to the numeric axis types only
+ bool numType = !this.IsAnyOrdinal;
+
+ // For autoranged values, assign the value. If appropriate, adjust the value by the
+ // "Grace" value.
+ if ( _minAuto )
+ {
+ _min = minVal;
+ // Do not let the grace value extend the axis below zero when all the values were positive
+ if ( numType && ( _min < 0 || minVal - _minGrace * range >= 0.0 ) )
+ _min = minVal - _minGrace * range;
+ }
+ if ( _maxAuto )
+ {
+ _max = maxVal;
+ // Do not let the grace value extend the axis above zero when all the values were negative
+ if ( numType && ( _max > 0 || maxVal + _maxGrace * range <= 0.0 ) )
+ _max = maxVal + _maxGrace * range;
+ }
+
+ if ( _max == _min && _maxAuto && _minAuto )
+ {
+ if ( Math.Abs( _max ) > 1e-100 )
+ {
+ _max *= ( _min < 0 ? 0.95 : 1.05 );
+ _min *= ( _min < 0 ? 1.05 : 0.95 );
+ }
+ else
+ {
+ _max = 1.0;
+ _min = -1.0;
+ }
+ }
+
+ if ( _max <= _min )
+ {
+ if ( _maxAuto )
+ _max = _min + 1.0;
+ else if ( _minAuto )
+ _min = _max - 1.0;
+ }
+
+ }
+
+ /// <summary>
+ /// Calculate the maximum number of labels that will fit on this axis.
+ /// </summary>
+ /// <remarks>
+ /// This method works for
+ /// both X and Y direction axes, and it works for angled text (assuming that a bounding box
+ /// is an appropriate measure). Technically, labels at 45 degree angles could fit better than
+ /// the return value of this method since the bounding boxes can overlap without the labels actually
+ /// overlapping.
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ public int CalcMaxLabels( Graphics g, GraphPane pane, float scaleFactor )
+ {
+ SizeF size = this.GetScaleMaxSpace( g, pane, scaleFactor, false );
+
+ // The font angles are already set such that the Width is parallel to the appropriate (X or Y)
+ // axis. Therefore, we always use size.Width.
+ // use the minimum of 1/4 the max Width or 1 character space
+ // double allowance = this.Scale.FontSpec.GetWidth( g, scaleFactor );
+ // if ( allowance > size.Width / 4 )
+ // allowance = size.Width / 4;
+
+
+ float maxWidth = 1000;
+ float temp = 1000;
+ float costh = (float) Math.Abs( Math.Cos( _fontSpec.Angle * Math.PI / 180.0 ) );
+ float sinth = (float) Math.Abs( Math.Sin( _fontSpec.Angle * Math.PI / 180.0 ) );
+
+ if ( costh > 0.001 )
+ maxWidth = size.Width / costh;
+ if ( sinth > 0.001 )
+ temp = size.Height / sinth;
+ if ( temp < maxWidth )
+ maxWidth = temp;
+
+
+ //maxWidth = size.Width;
+ /*
+ if ( this is XAxis )
+ // Add an extra character width to leave a minimum of 1 character space between labels
+ maxWidth = size.Width + this.Scale.FontSpec.GetWidth( g, scaleFactor );
+ else
+ // For vertical spacing, we only need 1/2 character
+ maxWidth = size.Width + this.Scale.FontSpec.GetWidth( g, scaleFactor ) / 2.0;
+ */
+ if ( maxWidth <= 0 )
+ maxWidth = 1;
+
+
+ // Calculate the maximum number of labels
+ double width;
+ RectangleF chartRect = pane.Chart._rect;
+ if ( _ownerAxis is XAxis || _ownerAxis is X2Axis )
+ width = ( chartRect.Width == 0 ) ? pane.Rect.Width * 0.75 : chartRect.Width;
+ else
+ width = ( chartRect.Height == 0 ) ? pane.Rect.Height * 0.75 : chartRect.Height;
+
+ int maxLabels = (int) ( width / maxWidth );
+ if ( maxLabels <= 0 )
+ maxLabels = 1;
+
+ return maxLabels;
+ }
+
+ internal void SetScaleMag( double min, double max, double step )
+ {
+ // set the scale magnitude if required
+ if ( _magAuto )
+ {
+ // Find the optimal scale display multiple
+ double mag = -100;
+ double mag2 = -100;
+
+ if ( Math.Abs( _min ) > 1.0e-30 )
+ mag = Math.Floor( Math.Log10( Math.Abs( _min ) ) );
+ if ( Math.Abs( _max ) > 1.0e-30 )
+ mag2 = Math.Floor( Math.Log10( Math.Abs( _max ) ) );
+
+ mag = Math.Max( mag2, mag );
+
+ // Do not use scale multiples for magnitudes below 4
+ if ( mag == -100 || Math.Abs( mag ) <= 3 )
+ mag = 0;
+
+ // Use a power of 10 that is a multiple of 3 (engineering scale)
+ _mag = (int) ( Math.Floor( mag / 3.0 ) * 3.0 );
+ }
+
+ // Calculate the appropriate number of dec places to display if required
+ if ( _formatAuto )
+ {
+ int numDec = 0 - (int) ( Math.Floor( Math.Log10( _majorStep ) ) - _mag );
+ if ( numDec < 0 )
+ numDec = 0;
+ _format = "f" + numDec.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Calculate a step size based on a data range.
+ /// </summary>
+ /// <remarks>
+ /// This utility method
+ /// will try to honor the <see cref="Default.TargetXSteps"/> and
+ /// <see cref="Default.TargetYSteps"/> number of
+ /// steps while using a rational increment (1, 2, or 5 -- which are
+ /// even divisors of 10). This method is used by <see cref="PickScale"/>.
+ /// </remarks>
+ /// <param name="range">The range of data in user scale units. This can
+ /// be a full range of the data for the major step size, or just the
+ /// value of the major step size to calculate the minor step size</param>
+ /// <param name="targetSteps">The desired "typical" number of steps
+ /// to divide the range into</param>
+ /// <returns>The calculated step size for the specified data range.</returns>
+ protected static double CalcStepSize( double range, double targetSteps )
+ {
+ // Calculate an initial guess at step size
+ double tempStep = range / targetSteps;
+
+ // Get the magnitude of the step size
+ double mag = Math.Floor( Math.Log10( tempStep ) );
+ double magPow = Math.Pow( (double) 10.0, mag );
+
+ // Calculate most significant digit of the new step size
+ double magMsd = ( (int) ( tempStep / magPow + .5 ) );
+
+ // promote the MSD to either 1, 2, or 5
+ if ( magMsd > 5.0 )
+ magMsd = 10.0;
+ else if ( magMsd > 2.0 )
+ magMsd = 5.0;
+ else if ( magMsd > 1.0 )
+ magMsd = 2.0;
+
+ return magMsd * magPow;
+ }
+
+ /// <summary>
+ /// Calculate a step size based on a data range, limited to a maximum number of steps.
+ /// </summary>
+ /// <remarks>
+ /// This utility method
+ /// will calculate a step size, of no more than maxSteps,
+ /// using a rational increment (1, 2, or 5 -- which are
+ /// even divisors of 10). This method is used by <see cref="PickScale"/>.
+ /// </remarks>
+ /// <param name="range">The range of data in user scale units. This can
+ /// be a full range of the data for the major step size, or just the
+ /// value of the major step size to calculate the minor step size</param>
+ /// <param name="maxSteps">The maximum allowable number of steps
+ /// to divide the range into</param>
+ /// <returns>The calculated step size for the specified data range.</returns>
+ protected double CalcBoundedStepSize( double range, double maxSteps )
+ {
+ // Calculate an initial guess at step size
+ double tempStep = range / maxSteps;
+
+ // Get the magnitude of the step size
+ double mag = Math.Floor( Math.Log10( tempStep ) );
+ double magPow = Math.Pow( (double) 10.0, mag );
+
+ // Calculate most significant digit of the new step size
+ double magMsd = Math.Ceiling( tempStep / magPow );
+
+ // promote the MSD to either 1, 2, or 5
+ if ( magMsd > 5.0 )
+ magMsd = 10.0;
+ else if ( magMsd > 2.0 )
+ magMsd = 5.0;
+ else if ( magMsd > 1.0 )
+ magMsd = 2.0;
+
+ return magMsd * magPow;
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first and last major axis label.
+ /// </summary>
+ /// <returns>
+ /// This is the total number of major tics for this axis.
+ /// </returns>
+ virtual internal int CalcNumTics()
+ {
+ int nTics = 1;
+
+ // default behavior is for a linear or ordinal scale
+ nTics = (int) ( ( _max - _min ) / _majorStep + 0.01 ) + 1;
+
+ if ( nTics < 1 )
+ nTics = 1;
+ else if ( nTics > 1000 )
+ nTics = 1000;
+
+ return nTics;
+ }
+
+ /// <summary>
+ /// Calculate the modulus (remainder) in a safe manner so that divide
+ /// by zero errors are avoided
+ /// </summary>
+ /// <param name="x">The divisor</param>
+ /// <param name="y">The dividend</param>
+ /// <returns>the value of the modulus, or zero for the divide-by-zero
+ /// case</returns>
+ protected double MyMod( double x, double y )
+ {
+ double temp;
+
+ if ( y == 0 )
+ return 0;
+
+ temp = x / y;
+ return y * ( temp - Math.Floor( temp ) );
+ }
+
+ /// <summary>
+ /// Define suitable default ranges for an axis in the event that
+ /// no data were available
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> of interest</param>
+ /// <param name="axis">The <see cref="Axis"/> for which to set the range</param>
+ internal void SetRange( GraphPane pane, Axis axis )
+ {
+ if ( _rangeMin >= Double.MaxValue || _rangeMax <= Double.MinValue )
+ {
+ // If this is a Y axis, and the main Y axis is valid, use it for defaults
+ if (axis != pane.XAxis && axis != pane.X2Axis && pane.YAxis != null &&
+ pane.YAxis.Scale._rangeMin < double.MaxValue && pane.YAxis.Scale._rangeMax > double.MinValue )
+ {
+ _rangeMin = pane.YAxis.Scale._rangeMin;
+ _rangeMax = pane.YAxis.Scale._rangeMax;
+ }
+ // Otherwise, if this is a Y axis, and the main Y2 axis is valid, use it for defaults
+ else if (axis != pane.XAxis && axis != pane.X2Axis && pane.Y2Axis != null &&
+ pane.Y2Axis.Scale._rangeMin < double.MaxValue && pane.Y2Axis.Scale._rangeMax > double.MinValue )
+ {
+ _rangeMin = pane.Y2Axis.Scale._rangeMin;
+ _rangeMax = pane.Y2Axis.Scale._rangeMax;
+ }
+ // Otherwise, just use 0 and 1
+ else
+ {
+ _rangeMin = 0;
+ _rangeMax = 1;
+ }
+
+ }
+
+ /*
+ if ( yMinVal >= Double.MaxValue || yMaxVal <= Double.MinValue )
+ {
+ if ( y2MinVal < Double.MaxValue && y2MaxVal > Double.MinValue )
+ {
+ yMinVal = y2MinVal;
+ yMaxVal = y2MaxVal;
+ }
+ else
+ {
+ yMinVal = 0;
+ yMaxVal = 0.01;
+ }
+ }
+
+ if ( y2MinVal >= Double.MaxValue || y2MaxVal <= Double.MinValue )
+ {
+ if ( yMinVal < Double.MaxValue && yMaxVal > Double.MinValue )
+ {
+ y2MinVal = yMinVal;
+ y2MaxVal = yMaxVal;
+ }
+ else
+ {
+ y2MinVal = 0;
+ y2MaxVal = 1;
+ }
+ }
+ */
+ }
+
+ #endregion
+
+ #region Coordinate Transform Methods
+
+ /// <summary>
+ /// Transform the coordinate value from user coordinates (scale value)
+ /// to graphics device coordinates (pixels).
+ /// </summary>
+ /// <remarks>This method takes into
+ /// account the scale range (<see cref="Min"/> and <see cref="Max"/>),
+ /// logarithmic state (<see cref="IsLog"/>), scale reverse state
+ /// (<see cref="IsReverse"/>) and axis type (<see cref="XAxis"/>,
+ /// <see cref="YAxis"/>, or <see cref="Y2Axis"/>).
+ /// Note that the <see cref="Chart.Rect"/> must be valid, and
+ /// <see cref="SetupScaleData"/> must be called for the
+ /// current configuration before using this method (this is called everytime
+ /// the graph is drawn (i.e., <see cref="GraphPane.Draw"/> is called).
+ /// </remarks>
+ /// <param name="x">The coordinate value, in user scale units, to
+ /// be transformed</param>
+ /// <returns>the coordinate value transformed to screen coordinates
+ /// for use in calling the <see cref="Graphics"/> draw routines</returns>
+ public float Transform( double x )
+ {
+ // Must take into account Log, and Reverse Axes
+ double denom = ( _maxLinTemp - _minLinTemp );
+ double ratio;
+ if ( denom > 1e-100 )
+ ratio = ( Linearize( x ) - _minLinTemp ) / denom;
+ else
+ ratio = 0;
+
+ // _isReverse axisType Eqn
+ // T XAxis _maxPix - ...
+ // F YAxis _maxPix - ...
+ // F Y2Axis _maxPix - ...
+
+ // T YAxis _minPix + ...
+ // T Y2Axis _minPix + ...
+ // F XAxis _minPix + ...
+
+ if ( _isReverse == ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) )
+ return (float) ( _maxPix - ( _maxPix - _minPix ) * ratio );
+ else
+ return (float) ( _minPix + ( _maxPix - _minPix ) * ratio );
+ }
+
+ /// <summary>
+ /// Transform the coordinate value from user coordinates (scale value)
+ /// to graphics device coordinates (pixels).
+ /// </summary>
+ /// <remarks>
+ /// This method takes into
+ /// account the scale range (<see cref="Min"/> and <see cref="Max"/>),
+ /// logarithmic state (<see cref="IsLog"/>), scale reverse state
+ /// (<see cref="IsReverse"/>) and axis type (<see cref="XAxis"/>,
+ /// <see cref="YAxis"/>, or <see cref="Y2Axis"/>).
+ /// Note that the <see cref="Chart.Rect"/> must be valid, and
+ /// <see cref="SetupScaleData"/> must be called for the
+ /// current configuration before using this method (this is called everytime
+ /// the graph is drawn (i.e., <see cref="GraphPane.Draw"/> is called).
+ /// </remarks>
+ /// <param name="isOverrideOrdinal">true to force the axis to honor the data
+ /// value, rather than replacing it with the ordinal value</param>
+ /// <param name="i">The ordinal value of this point, just in case
+ /// this is an <see cref="AxisType.Ordinal"/> axis</param>
+ /// <param name="x">The coordinate value, in user scale units, to
+ /// be transformed</param>
+ /// <returns>the coordinate value transformed to screen coordinates
+ /// for use in calling the <see cref="Graphics"/> draw routines</returns>
+ public float Transform( bool isOverrideOrdinal, int i, double x )
+ {
+ // ordinal types ignore the X value, and just use the ordinal position
+ if ( this.IsAnyOrdinal && i >= 0 && !isOverrideOrdinal )
+ x = (double) i + 1.0;
+ return Transform( x );
+
+ }
+
+ /// <summary>
+ /// Reverse transform the user coordinates (scale value)
+ /// given a graphics device coordinate (pixels).
+ /// </summary>
+ /// <remarks>
+ /// This method takes into
+ /// account the scale range (<see cref="Min"/> and <see cref="Max"/>),
+ /// logarithmic state (<see cref="IsLog"/>), scale reverse state
+ /// (<see cref="IsReverse"/>) and axis type (<see cref="XAxis"/>,
+ /// <see cref="YAxis"/>, or <see cref="Y2Axis"/>).
+ /// Note that the <see cref="Chart.Rect"/> must be valid, and
+ /// <see cref="SetupScaleData"/> must be called for the
+ /// current configuration before using this method (this is called everytime
+ /// the graph is drawn (i.e., <see cref="GraphPane.Draw"/> is called).
+ /// </remarks>
+ /// <param name="pixVal">The screen pixel value, in graphics device coordinates to
+ /// be transformed</param>
+ /// <returns>The user scale value that corresponds to the screen pixel location</returns>
+ public double ReverseTransform( float pixVal )
+ {
+ double val;
+
+ // see if the sign of the equation needs to be reversed
+ if ( ( _isReverse ) == ( _ownerAxis is XAxis || _ownerAxis is X2Axis ) )
+ val = (double) ( pixVal - _maxPix )
+ / (double) ( _minPix - _maxPix )
+ * ( _maxLinTemp - _minLinTemp ) + _minLinTemp;
+ else
+ val = (double) ( pixVal - _minPix )
+ / (double) ( _maxPix - _minPix )
+ * ( _maxLinTemp - _minLinTemp ) + _minLinTemp;
+
+ return DeLinearize( val );
+ }
+
+
+ /// <summary>
+ /// Transform the coordinate value from user coordinates (scale value)
+ /// to graphics device coordinates (pixels).
+ /// </summary>
+ /// <remarks>Assumes that the origin
+ /// has been set to the "left" of this axis, facing from the label side.
+ /// Note that the left side corresponds to the scale minimum for the X and
+ /// Y2 axes, but it is the scale maximum for the Y axis.
+ /// This method takes into
+ /// account the scale range (<see cref="Min"/> and <see cref="Max"/>),
+ /// logarithmic state (<see cref="IsLog"/>), scale reverse state
+ /// (<see cref="IsReverse"/>) and axis type (<see cref="XAxis"/>,
+ /// <see cref="YAxis"/>, or <see cref="Y2Axis"/>). Note that
+ /// the <see cref="Chart.Rect"/> must be valid, and
+ /// <see cref="SetupScaleData"/> must be called for the
+ /// current configuration before using this method.
+ /// </remarks>
+ /// <param name="x">The coordinate value, in linearized user scale units, to
+ /// be transformed</param>
+ /// <returns>the coordinate value transformed to screen coordinates
+ /// for use in calling the <see cref="Draw"/> method</returns>
+ public float LocalTransform( double x )
+ {
+ // Must take into account Log, and Reverse Axes
+ double ratio;
+ float rv;
+
+ // Coordinate values for log scales are already in exponent form, so no need
+ // to take the log here
+ ratio = ( x - _minLinTemp ) /
+ ( _maxLinTemp - _minLinTemp );
+
+ if ( _isReverse == ( _ownerAxis is YAxis || _ownerAxis is X2Axis ) )
+ rv = (float) ( ( _maxPix - _minPix ) * ratio );
+ else
+ rv = (float)( ( _maxPix - _minPix ) * ( 1.0F - ratio ) );
+
+ return rv;
+ }
+
+ /// <summary>
+ /// Calculate a base 10 logarithm in a safe manner to avoid math exceptions
+ /// </summary>
+ /// <param name="x">The value for which the logarithm is to be calculated</param>
+ /// <returns>The value of the logarithm, or 0 if the <paramref name="x"/>
+ /// argument was negative or zero</returns>
+ public static double SafeLog( double x )
+ {
+ if ( x > 1.0e-20 )
+ return Math.Log10( x );
+ else
+ return 0.0;
+ }
+
+ ///<summary>
+ ///Calculate an exponential in a safe manner to avoid math exceptions
+ ///</summary>
+ /// <param name="x">The value for which the exponential is to be calculated</param>
+ /// <param name="exponent">The exponent value to use for calculating the exponential.</param>
+ public static double SafeExp( double x, double exponent )
+ {
+ if ( x > 1.0e-20 )
+ return Math.Pow( x, exponent );
+ else
+ return 0.0;
+ }
+
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/ScaleState.cs b/ZedGraph/ScaleState.cs
new file mode 100644
index 0000000..da3210f
--- /dev/null
+++ b/ZedGraph/ScaleState.cs
@@ -0,0 +1,186 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Text;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that captures an <see cref="Axis"/> scale range.
+ /// </summary>
+ /// <remarks>This structure is used by the <see cref="ZoomState"/> class to store
+ /// <see cref="Axis"/> scale range settings in a collection for later retrieval.
+ /// The class stores the <see cref="Scale.Min"/>, <see cref="Scale.Max"/>,
+ /// <see cref="Scale.MinorStep"/>, and <see cref="Scale.MajorStep"/> properties, along with
+ /// the corresponding auto-scale settings: <see cref="Scale.MinAuto"/>,
+ /// <see cref="Scale.MaxAuto"/>, <see cref="Scale.MinorStepAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/>.</remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.2 $ $Date: 2007-02-19 08:05:24 $ </version>
+ public class ScaleState : ICloneable
+ {
+ /// <summary>
+ /// The axis range data for <see cref="Scale.Min"/>, <see cref="Scale.Max"/>,
+ /// <see cref="Scale.MinorStep"/>, and <see cref="Scale.MajorStep"/>
+ /// </summary>
+ private double _min, _minorStep, _majorStep, _max;
+ /// <summary>
+ /// The status of <see cref="Scale.MinAuto"/>,
+ /// <see cref="Scale.MaxAuto"/>, <see cref="Scale.MinorStepAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/>
+ /// </summary>
+ private bool _minAuto, _minorStepAuto,
+ _majorStepAuto, _maxAuto,
+ _formatAuto, _magAuto;
+
+ /// <summary>
+ /// The status of <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ private DateUnit _minorUnit, _majorUnit;
+
+ private string _format;
+ private int _mag;
+
+ /// <summary>
+ /// Construct a <see cref="ScaleState"/> from the specified <see cref="Axis"/>
+ /// </summary>
+ /// <param name="axis">The <see cref="Axis"/> from which to collect the scale
+ /// range settings.</param>
+ public ScaleState( Axis axis )
+ {
+ _min = axis._scale._min;
+ _minorStep = axis._scale._minorStep;
+ _majorStep = axis._scale._majorStep;
+ _max = axis._scale._max;
+ _majorUnit = axis._scale._majorUnit;
+ _minorUnit = axis._scale._minorUnit;
+
+ _format = axis._scale._format;
+ _mag = axis._scale._mag;
+ //this.numDec = axis.NumDec;
+
+ _minAuto = axis._scale._minAuto;
+ _majorStepAuto = axis._scale._majorStepAuto;
+ _minorStepAuto = axis._scale._minorStepAuto;
+ _maxAuto = axis._scale._maxAuto;
+
+ _formatAuto = axis._scale._formatAuto;
+ _magAuto = axis._scale._magAuto;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ScaleState"/> object from which to copy</param>
+ public ScaleState( ScaleState rhs )
+ {
+ _min = rhs._min;
+ _majorStep = rhs._majorStep;
+ _minorStep = rhs._minorStep;
+ _max = rhs._max;
+ _majorUnit = rhs._majorUnit;
+ _minorUnit = rhs._minorUnit;
+
+ _format = rhs._format;
+ _mag = rhs._mag;
+
+ _minAuto = rhs._minAuto;
+ _majorStepAuto = rhs._majorStepAuto;
+ _minorStepAuto = rhs._minorStepAuto;
+ _maxAuto = rhs._maxAuto;
+
+ _formatAuto = rhs._formatAuto;
+ _magAuto = rhs._magAuto;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ScaleState Clone()
+ {
+ return new ScaleState( this );
+ }
+
+ /// <summary>
+ /// Copy the properties from this <see cref="ScaleState"/> out to the specified <see cref="Axis"/>.
+ /// </summary>
+ /// <param name="axis">The <see cref="Axis"/> reference to which the properties should be
+ /// copied</param>
+ public void ApplyScale( Axis axis )
+ {
+ axis._scale._min = _min;
+ axis._scale._majorStep = _majorStep;
+ axis._scale._minorStep = _minorStep;
+ axis._scale._max = _max;
+ axis._scale._majorUnit = _majorUnit;
+ axis._scale._minorUnit = _minorUnit;
+
+ axis._scale._format = _format;
+ axis._scale._mag = _mag;
+
+ // The auto settings must be made after the min/step/max settings, since setting those
+ // properties actually affects the auto settings.
+ axis._scale._minAuto = _minAuto;
+ axis._scale._minorStepAuto = _minorStepAuto;
+ axis._scale._majorStepAuto = _majorStepAuto;
+ axis._scale._maxAuto = _maxAuto;
+
+ axis._scale._formatAuto = _formatAuto;
+ axis._scale._magAuto = _magAuto;
+
+ }
+
+ /// <summary>
+ /// Determine if the state contained in this <see cref="ScaleState"/> object is different from
+ /// the state of the specified <see cref="Axis"/>.
+ /// </summary>
+ /// <param name="axis">The <see cref="Axis"/> object with which to compare states.</param>
+ /// <returns>true if the states are different, false otherwise</returns>
+ public bool IsChanged( Axis axis )
+ {
+ return axis._scale._min != _min ||
+ axis._scale._majorStep != _majorStep ||
+ axis._scale._minorStep != _minorStep ||
+ axis._scale._max != _max ||
+ axis._scale._minorUnit != _minorUnit ||
+ axis._scale._majorUnit != _majorUnit ||
+ axis._scale._minAuto != _minAuto ||
+ axis._scale._minorStepAuto != _minorStepAuto ||
+ axis._scale._majorStepAuto != _majorStepAuto ||
+ axis._scale._maxAuto != _maxAuto;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/ScaleStateList.cs b/ZedGraph/ScaleStateList.cs
new file mode 100644
index 0000000..71b1915
--- /dev/null
+++ b/ZedGraph/ScaleStateList.cs
@@ -0,0 +1,178 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class that maintains a list of <see cref="ScaleState" />
+ /// objects, corresponding to the list of <see cref="Axis" /> objects
+ /// from <see cref="GraphPane.YAxisList" /> or <see cref="GraphPane.Y2AxisList" />.
+ /// </summary>
+ public class ScaleStateList : List<ScaleState>, ICloneable
+ {
+ /// <summary>
+ /// Construct a new <see cref="ScaleStateList" /> automatically from an
+ /// existing <see cref="YAxisList" />.
+ /// </summary>
+ /// <param name="list">The <see cref="YAxisList" /> (a list of Y axes),
+ /// from which to retrieve the state and create the <see cref="ScaleState" />
+ /// objects.</param>
+ public ScaleStateList( YAxisList list )
+ {
+ foreach ( Axis axis in list )
+ this.Add( new ScaleState( axis ) );
+ }
+
+ /// <summary>
+ /// Construct a new <see cref="ScaleStateList" /> automatically from an
+ /// existing <see cref="Y2AxisList" />.
+ /// </summary>
+ /// <param name="list">The <see cref="Y2AxisList" /> (a list of Y axes),
+ /// from which to retrieve the state and create the <see cref="ScaleState" />
+ /// objects.</param>
+ public ScaleStateList( Y2AxisList list )
+ {
+ foreach ( Axis axis in list )
+ this.Add( new ScaleState( axis ) );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ScaleStateList"/> object from which to copy</param>
+ public ScaleStateList( ScaleStateList rhs )
+ {
+ foreach ( ScaleState item in rhs )
+ {
+ this.Add( item.Clone() );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ScaleStateList Clone()
+ {
+ return new ScaleStateList( this );
+ }
+
+ /// <summary>
+ /// Iterate through the list of <see cref="ScaleState" /> objects, comparing them
+ /// to the state of the specified <see cref="YAxisList" /> <see cref="Axis" />
+ /// objects.
+ /// </summary>
+ /// <param name="list">A <see cref="YAxisList" /> object specifying a list of
+ /// <see cref="Axis" /> objects to be compared with this <see cref="ScaleStateList" />.
+ /// </param>
+ /// <returns>true if a difference is found, false otherwise</returns>
+ public bool IsChanged( YAxisList list )
+ {
+ int count = Math.Min( list.Count, this.Count );
+ for ( int i = 0; i < count; i++ )
+ if ( this[i].IsChanged( list[i] ) )
+ return true;
+
+ return false;
+ }
+
+ /// <summary>
+ /// Iterate through the list of <see cref="ScaleState" /> objects, comparing them
+ /// to the state of the specified <see cref="Y2AxisList" /> <see cref="Axis" />
+ /// objects.
+ /// </summary>
+ /// <param name="list">A <see cref="Y2AxisList" /> object specifying a list of
+ /// <see cref="Axis" /> objects to be compared with this <see cref="ScaleStateList" />.
+ /// </param>
+ /// <returns>true if a difference is found, false otherwise</returns>
+ public bool IsChanged( Y2AxisList list )
+ {
+ int count = Math.Min( list.Count, this.Count );
+ for ( int i = 0; i < count; i++ )
+ if ( this[i].IsChanged( list[i] ) )
+ return true;
+
+ return false;
+ }
+ /*
+ /// <summary>
+ /// Indexer to access the specified <see cref="ScaleState"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="ScaleState"/> object to be accessed.</param>
+ /// <value>A <see cref="ScaleState"/> object reference.</value>
+ public ScaleState this[ int index ]
+ {
+ get { return (ScaleState) List[index]; }
+ set { List[index] = value; }
+ }
+ /// <summary>
+ /// Add a <see cref="ScaleState"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="state">A reference to the <see cref="ScaleState"/> object to
+ /// be added</param>
+ /// <seealso cref="IList.Add"/>
+ public void Add( ScaleState state )
+ {
+ List.Add( state );
+ }
+ */
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="list"></param>
+ public void ApplyScale( YAxisList list )
+ {
+ int count = Math.Min( list.Count, this.Count );
+ for ( int i = 0; i < count; i++ )
+ this[i].ApplyScale( list[i] );
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="list"></param>
+ public void ApplyScale( Y2AxisList list )
+ {
+ int count = Math.Min( list.Count, this.Count );
+ for ( int i = 0; i < count; i++ )
+ this[i].ApplyScale( list[i] );
+ }
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/ScrollRange.cs b/ZedGraph/ScrollRange.cs
new file mode 100644
index 0000000..b3145e0
--- /dev/null
+++ b/ZedGraph/ScrollRange.cs
@@ -0,0 +1,97 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A simple struct to store minimum and maximum <see cref="double" /> type
+ /// values for the scroll range
+ /// </summary>
+ public struct ScrollRange
+ {
+ private bool _isScrollable;
+ private double _min;
+ private double _max;
+
+ /// <summary>
+ /// Construct a <see cref="ScrollRange" /> object given the specified data values.
+ /// </summary>
+ /// <param name="min">The minimum axis value limit for the scroll bar</param>
+ /// <param name="max">The maximum axis value limit for the scroll bar</param>
+ /// <param name="isScrollable">true to make this item scrollable, false otherwise</param>
+ public ScrollRange( double min, double max, bool isScrollable )
+ {
+ _min = min;
+ _max = max;
+ _isScrollable = isScrollable;
+ }
+
+ /// <summary>
+ /// Sets the scroll range to default values of zero, and sets the <see cref="IsScrollable" />
+ /// property as specified.
+ /// </summary>
+ /// <param name="isScrollable">true to make this item scrollable, false otherwise</param>
+ public ScrollRange( bool isScrollable )
+ {
+ _min = 0.0;
+ _max = 0.0;
+ _isScrollable = isScrollable;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ScrollRange"/> object from which to copy</param>
+ public ScrollRange( ScrollRange rhs )
+ {
+ _min = rhs._min;
+ _max = rhs._max;
+ _isScrollable = rhs._isScrollable;
+ }
+
+ /// <summary>
+ /// Gets or sets a property that determines if the <see cref="Axis" /> corresponding to
+ /// this <see cref="ScrollRange" /> object can be scrolled.
+ /// </summary>
+ public bool IsScrollable
+ {
+ get { return _isScrollable; }
+ set { _isScrollable = value; }
+ }
+
+ /// <summary>
+ /// The minimum axis value limit for the scroll bar.
+ /// </summary>
+ public double Min
+ {
+ get { return _min; }
+ set { _min = value; }
+ }
+ /// <summary>
+ /// The maximum axis value limit for the scroll bar.
+ /// </summary>
+ public double Max
+ {
+ get { return _max; }
+ set { _max = value; }
+ }
+ }
+}
diff --git a/ZedGraph/ScrollRangeList.cs b/ZedGraph/ScrollRangeList.cs
new file mode 100644
index 0000000..2c5c611
--- /dev/null
+++ b/ZedGraph/ScrollRangeList.cs
@@ -0,0 +1,129 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="ScrollRange"/> objects.
+ /// </summary>
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.3 $ $Date: 2006-06-24 20:26:43 $ </version>
+ public class ScrollRangeList : List<ScrollRange>, ICloneable
+ {
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the collection class.
+ /// </summary>
+ public ScrollRangeList()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ScrollRangeList"/> object from which to copy</param>
+ public ScrollRangeList( ScrollRangeList rhs )
+ {
+ foreach ( ScrollRange item in rhs )
+ this.Add( new ScrollRange( item ) );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ScrollRangeList Clone()
+ {
+ return new ScrollRangeList( this );
+ }
+
+
+ #endregion
+
+ #region List Methods
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="ScrollRange"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="ScrollRange"/> object to be accessed.</param>
+ /// <value>A <see cref="ScrollRange"/> object instance</value>
+ public new ScrollRange this[ int index ]
+ {
+ get
+ {
+ if ( index < 0 || index >= this.Count )
+ return new ScrollRange( false );
+ else
+ return (ScrollRange) base[index];
+ }
+ set { base[index] = value; }
+ }
+
+ /* /// <summary>
+ /// Add a <see cref="ScrollRange"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="item">The <see cref="ScrollRange"/> object to be added</param>
+ /// <seealso cref="IList.Add"/>
+ public int Add( ScrollRange item )
+ {
+ return List.Add( item );
+ }
+ /// <summary>
+ /// Insert a <see cref="ScrollRange"/> object into the collection at the specified
+ /// zero-based index location.
+ /// </summary>
+ /// <param name="index">The zero-based index location for insertion.</param>
+ /// <param name="item">The <see cref="ScrollRange"/> object that is to be
+ /// inserted.</param>
+ /// <seealso cref="IList.Insert"/>
+ public void Insert( int index, ScrollRange item )
+ {
+ List.Insert( index, item );
+ }
+ */
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Selection.cs b/ZedGraph/Selection.cs
new file mode 100644
index 0000000..dc0d2cb
--- /dev/null
+++ b/ZedGraph/Selection.cs
@@ -0,0 +1,258 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2007 John Champion and JCarpenter
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// </summary>
+ /// <remarks>
+ /// </remarks>
+ ///
+ /// <author> John Champion and JCarpenter </author>
+ /// <version> $Revision: 3.5 $ $Date: 2007-03-11 02:08:16 $ </version>
+ public class Selection : CurveList
+ {
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Subscribe to this event to receive notice
+ /// that the list of selected CurveItems has changed
+ /// </summary>
+ public event EventHandler SelectionChangedEvent;
+
+ #region static properties
+
+ /// <summary>
+ /// The <see cref="Border" /> type to be used for drawing "selected"
+ /// <see cref="PieItem" />, <see cref="BarItem" />, <see cref="HiLowBarItem" />,
+ /// <see cref="OHLCBarItem" />, and <see cref="JapaneseCandleStickItem" /> item types.
+ /// </summary>
+ public static Border Border = new Border( Color.Gray, 1.0f );
+ /// <summary>
+ /// The <see cref="Fill" /> type to be used for drawing "selected"
+ /// <see cref="PieItem" />, <see cref="BarItem" />, <see cref="HiLowBarItem" />,
+ /// and <see cref="JapaneseCandleStickItem" /> item types.
+ /// </summary>
+ public static Fill Fill = new Fill( Color.Gray );
+ /// <summary>
+ /// The <see cref="Line" /> type to be used for drawing "selected"
+ /// <see cref="LineItem" /> and <see cref="StickItem" /> types
+ /// </summary>
+ public static Line Line = new Line( Color.Gray );
+ // public static ErrorBar ErrorBar = new ErrorBar( Color.Gray );
+ /// <summary>
+ /// The <see cref="Symbol" /> type to be used for drawing "selected"
+ /// <see cref="LineItem" /> and <see cref="ErrorBarItem" /> types.
+ /// </summary>
+ public static Symbol Symbol = new Symbol( SymbolType.Circle, Color.Gray );
+
+ //public static Color SelectedSymbolColor = Color.Gray;
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Place a <see cref="CurveItem" /> in the selection list, removing all other
+ /// items.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that is the "owner"
+ /// of the <see cref="CurveItem" />'s.</param>
+ /// <param name="ci">The <see cref="CurveItem" /> to be added to the list.</param>
+ public void Select( MasterPane master, CurveItem ci )
+ {
+ //Clear the selection, but don't send the event,
+ //the event will be sent in "AddToSelection" by calling "UpdateSelection"
+ ClearSelection( master, false );
+
+ AddToSelection( master, ci );
+ }
+
+ /// <summary>
+ /// Place a list of <see cref="CurveItem" />'s in the selection list, removing all other
+ /// items.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that is the "owner"
+ /// of the <see cref="CurveItem" />'s.</param>
+ /// <param name="ciList">The list of <see cref="CurveItem" /> to be added to the list.</param>
+ public void Select( MasterPane master, CurveList ciList )
+ {
+ //Clear the selection, but don't send the event,
+ //the event will be sent in "AddToSelection" by calling "UpdateSelection"
+ ClearSelection( master, false );
+
+ AddToSelection( master, ciList );
+ }
+
+ /// <summary>
+ /// Add a <see cref="CurveItem" /> to the selection list.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that is the "owner"
+ /// of the <see cref="CurveItem" />'s.</param>
+ /// <param name="ci">The <see cref="CurveItem" /> to be added to the list.</param>
+ public void AddToSelection( MasterPane master, CurveItem ci )
+ {
+ if ( this.Contains( ci ) == false )
+ Add( ci );
+
+ UpdateSelection( master );
+ }
+
+ /// <summary>
+ /// Add a list of <see cref="CurveItem" />'s to the selection list.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that is the "owner"
+ /// of the <see cref="CurveItem" />'s.</param>
+ /// <param name="ciList">The list of <see cref="CurveItem" />'s to be added to the list.</param>
+ public void AddToSelection( MasterPane master, CurveList ciList )
+ {
+ foreach ( CurveItem ci in ciList )
+ {
+ if ( this.Contains( ci ) == false )
+ this.Add( ci );
+ }
+
+ UpdateSelection( master );
+ }
+
+#if ( DOTNET1 )
+
+ // Define a "Contains" method so that this class works with .Net 1.1 or 2.0
+ internal bool Contains( CurveItem item )
+ {
+ foreach ( CurveItem ci in this )
+ if ( item == ci )
+ return true;
+
+ return false;
+ }
+#endif
+
+ /// <summary>
+ /// Remove the specified <see cref="CurveItem" /> from the selection list.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that is the "owner"
+ /// of the <see cref="CurveItem" />'s.</param>
+ /// <param name="ci">The <see cref="CurveItem" /> to be removed from the list.</param>
+ public void RemoveFromSelection( MasterPane master, CurveItem ci )
+ {
+ if ( this.Contains( ci ) )
+ this.Remove( ci );
+
+ UpdateSelection( master );
+
+ }
+
+ /// <summary>
+ /// Clear the selection list and trigger a <see cref="SelectionChangedEvent" />.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that "owns" the selection list.</param>
+ public void ClearSelection( MasterPane master )
+ {
+ ClearSelection( master, true );
+ }
+
+ /// <summary>
+ /// Clear the selection list and optionally trigger a <see cref="SelectionChangedEvent" />.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that "owns" the selection list.</param>
+ /// <param name="sendEvent">true to trigger a <see cref="SelectionChangedEvent" />,
+ /// false otherwise.</param>
+ public void ClearSelection( MasterPane master, bool sendEvent )
+ {
+ this.Clear();
+
+ foreach ( GraphPane pane in master.PaneList )
+ {
+ foreach ( CurveItem ci in pane.CurveList )
+ {
+ ci.IsSelected = false;
+ }
+ }
+
+ if ( sendEvent )
+ {
+ if ( SelectionChangedEvent != null )
+ SelectionChangedEvent( this, new EventArgs() );
+ }
+ }
+
+ /// <summary>
+ /// Mark the <see cref="CurveItem" />'s that are included in the selection list
+ /// by setting the <see cref="CurveItem.IsSelected" /> property to true.
+ /// </summary>
+ /// <param name="master">The <see cref="MasterPane" /> that "owns" the selection list.</param>
+ public void UpdateSelection( MasterPane master )
+ {
+ if ( Count <= 0 )
+ {
+ ClearSelection( master );
+ return;
+ }
+
+ foreach ( GraphPane pane in master.PaneList )
+ {
+ foreach ( CurveItem ci in pane.CurveList )
+ {
+ //Make it Inactive
+ ci.IsSelected = false;
+ }
+
+ }
+ foreach ( CurveItem ci in this )
+ {
+ //Make Active
+ ci.IsSelected = true;
+
+ //If it is a line / scatterplot, the selected Curve may be occluded by an unselected Curve
+ //So, move it to the top of the ZOrder by removing it, and re-adding it.
+
+ //Why only do this for Lines? ...Bar and Pie Curves are less likely to overlap,
+ //and adding and removing Pie elements changes thier display order
+ if ( ci.IsLine )
+ {
+ //I don't know how to get a Pane, from a CurveItem, so I can only do it
+ //if there is one and only one Pane, based on the assumption that the
+ //Curve's Pane is MasterPane[0]
+
+ //If there is only one Pane
+ if ( master.PaneList.Count == 1 )
+ {
+ GraphPane pane = master.PaneList[0];
+ pane.CurveList.Remove( ci );
+ pane.CurveList.Insert( 0, ci );
+ }
+
+ }
+ }
+
+ //Send Selection Changed Event
+ if ( SelectionChangedEvent != null )
+ SelectionChangedEvent( this, new EventArgs() );
+
+ }
+
+ #endregion
+
+
+ }
+}
diff --git a/ZedGraph/StickItem.cs b/ZedGraph/StickItem.cs
new file mode 100644
index 0000000..66b438a
--- /dev/null
+++ b/ZedGraph/StickItem.cs
@@ -0,0 +1,218 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Encapsulates a curve type that is displayed as a series of vertical "sticks",
+ /// one at each defined point.
+ /// </summary>
+ /// <remarks>
+ /// The sticks run from the zero value of the Y axis, to the Y point defined in each
+ /// <see cref="PointPair"/> of the <see cref="IPointList" /> (see <see cref="CurveItem.Points"/>).
+ /// The properties of the sticks are defined in the <see cref="Line"/> property.
+ /// Normally, the <see cref="Symbol"/> is not visible. However, if you manually enable the
+ /// <see cref="Symbol"/> using the <see cref="ZedGraph.Symbol.IsVisible"/> property, the
+ /// symbols will be drawn at the "Z" value from each <see cref="PointPair" /> (see
+ /// <see cref="PointPair.Z" />).
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.7 $ $Date: 2007-01-25 07:56:09 $ </version>
+ [Serializable]
+ public class StickItem : LineItem, ICloneable, ISerializable
+ {
+ #region Fields
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the Z data are included, false otherwise</value>
+ override internal bool IsZIncluded( GraphPane pane )
+ {
+ return _symbol.IsVisible;
+ }
+
+ /// <summary>
+ /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
+ /// </param>
+ /// <value>true if the X axis is independent, false otherwise</value>
+ override internal bool IsXIndependent( GraphPane pane )
+ {
+ return true;
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Create a new <see cref="StickItem"/>, specifying only the legend <see cref="CurveItem.Label" />.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ public StickItem( string label ) : base( label )
+ {
+ _symbol.IsVisible = false;
+ }
+
+ /// <summary>
+ /// Create a new <see cref="StickItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ /// <param name="lineWidth">The width (in points) to be used for the <see cref="Line"/>. This
+ /// width is scaled based on <see cref="PaneBase.CalcScaleFactor"/>. Use a value of zero to
+ /// hide the line (see <see cref="ZedGraph.LineBase.IsVisible"/>).</param>
+ public StickItem( string label, double[] x, double[] y, Color color, float lineWidth )
+ : this( label, new PointPairList( x, y ), color, lineWidth )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="StickItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="x">An array of double precision values that define
+ /// the independent (X axis) values for this curve</param>
+ /// <param name="y">An array of double precision values that define
+ /// the dependent (Y axis) values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ public StickItem( string label, double[] x, double[] y, Color color )
+ : this( label, new PointPairList( x, y ), color )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="StickItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ public StickItem( string label, IPointList points, Color color )
+ : this( label, points, color, ZedGraph.LineBase.Default.Width )
+ {
+ }
+
+ /// <summary>
+ /// Create a new <see cref="StickItem"/> using the specified properties.
+ /// </summary>
+ /// <param name="label">The label that will appear in the legend.</param>
+ /// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
+ /// the X and Y values for this curve</param>
+ /// <param name="color">A <see cref="Color"/> value that will be applied to
+ /// the <see cref="Line"/> and <see cref="Symbol"/> properties.
+ /// </param>
+ /// <param name="lineWidth">The width (in points) to be used for the <see cref="Line"/>. This
+ /// width is scaled based on <see cref="PaneBase.CalcScaleFactor"/>. Use a value of zero to
+ /// hide the line (see <see cref="ZedGraph.LineBase.IsVisible"/>).</param>
+ public StickItem( string label, IPointList points, Color color, float lineWidth )
+ : base( label, points, color, Symbol.Default.Type, lineWidth )
+ {
+ _symbol.IsVisible = false;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="StickItem"/> object from which to copy</param>
+ public StickItem( StickItem rhs ) : base( rhs )
+ {
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public new StickItem Clone()
+ {
+ return new StickItem( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected StickItem( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema3", schema3 );
+ }
+ #endregion
+
+ #region Methods
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/StockPointList.cs b/ZedGraph/StockPointList.cs
new file mode 100644
index 0000000..57ddef2
--- /dev/null
+++ b/ZedGraph/StockPointList.cs
@@ -0,0 +1,171 @@
+//============================================================================
+//PointPairList Class
+//Copyright � 2006 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="StockPt"/> objects
+ /// that define the set of points to be displayed on the curve.
+ /// </summary>
+ ///
+ /// <author> John Champion based on code by Jerry Vos</author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-02-18 05:51:54 $ </version>
+ [Serializable]
+ public class StockPointList : List<StockPt>, IPointList, IPointListEdit
+ {
+
+ #region Properties
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="StockPt"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="StockPt"/> object to be accessed.</param>
+ /// <value>A <see cref="StockPt"/> object reference.</value>
+ public new PointPair this[int index]
+ {
+ get { return base[index]; }
+ set { base[index] = new StockPt( value ); }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the collection class
+ /// </summary>
+ public StockPointList()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The StockPointList from which to copy</param>
+ public StockPointList( StockPointList rhs )
+ {
+ for ( int i = 0; i < rhs.Count; i++ )
+ {
+ StockPt pt = new StockPt( rhs[i] );
+ this.Add( pt );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public StockPointList Clone()
+ {
+ return new StockPointList( this );
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Add a <see cref="StockPt"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="point">The <see cref="StockPt"/> object to
+ /// be added</param>
+ new public void Add( StockPt point )
+ {
+ base.Add( new StockPt( point ) );
+ }
+
+ /// <summary>
+ /// Add a <see cref="PointPair"/> object to the collection at the end of the list.
+ /// </summary>
+ /// <param name="point">The <see cref="PointPair"/> object to be added</param>
+ public void Add( PointPair point )
+ {
+// throw new ArgumentException( "Error: Only the StockPt type can be added to StockPointList" +
+// ". An ordinary PointPair is not allowed" );
+ base.Add( new StockPt( point ) );
+ }
+
+ /// <summary>
+ /// Add a <see cref="StockPt"/> object to the collection at the end of the list using
+ /// the specified values. The unspecified values (low, open, close) are all set to
+ /// <see cref="PointPairBase.Missing" />.
+ /// </summary>
+ /// <param name="date">An <see cref="XDate" /> value</param>
+ /// <param name="high">The high value for the day</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ public void Add( double date, double high )
+ {
+ Add( new StockPt( date, high, PointPair.Missing, PointPair.Missing,
+ PointPair.Missing, PointPair.Missing ) );
+ }
+
+ /// <summary>
+ /// Add a single point to the <see cref="PointPairList"/> from values of type double.
+ /// </summary>
+ /// <param name="date">An <see cref="XDate" /> value</param>
+ /// <param name="high">The high value for the day</param>
+ /// <param name="low">The low value for the day</param>
+ /// <param name="open">The opening value for the day</param>
+ /// <param name="close">The closing value for the day</param>
+ /// <param name="vol">The trading volume for the day</param>
+ /// <returns>The zero-based ordinal index where the point was added in the list.</returns>
+ public void Add( double date, double high, double low, double open, double close, double vol )
+ {
+ StockPt point = new StockPt( date, high, low, open, close, vol );
+ Add( point );
+ }
+
+ /// <summary>
+ /// Access the <see cref="StockPt" /> at the specified ordinal index.
+ /// </summary>
+ /// <remarks>
+ /// To be compatible with the <see cref="IPointList" /> interface, the
+ /// <see cref="StockPointList" /> must implement an index that returns a
+ /// <see cref="PointPair" /> rather than a <see cref="StockPt" />. This method
+ /// will return the actual <see cref="StockPt" /> at the specified position.
+ /// </remarks>
+ /// <param name="index">The ordinal position (zero-based) in the list</param>
+ /// <returns>The specified <see cref="StockPt" />.
+ /// </returns>
+ public StockPt GetAt( int index )
+ {
+ return base[index];
+ }
+
+ #endregion
+ }
+}
+
+
diff --git a/ZedGraph/StockPt.cs b/ZedGraph/StockPt.cs
new file mode 100644
index 0000000..b70d871
--- /dev/null
+++ b/ZedGraph/StockPt.cs
@@ -0,0 +1,315 @@
+//============================================================================
+//PointPair4 Class
+//Copyright � 2006 Jerry Vos & John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using IComparer = System.Collections.IComparer;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The basic <see cref="PointPair" /> class holds three data values (X, Y, Z). This
+ /// class extends the basic PointPair to contain five data values (X, Y, Z, Open, Close).
+ /// </summary>
+ /// <remarks>
+ /// The values are remapped to <see cref="Date" />, <see cref="High" />,
+ /// <see cref="Low" />, <see cref="Open" />, and <see cref="Close" />.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-02-07 07:46:46 $ </version>
+ [Serializable]
+ public class StockPt : PointPair, ISerializable
+ {
+
+ #region Member variables
+
+ // member variable mapping:
+ // Date = X
+ // High = Y
+ // Low = Z
+ // Open = Open
+ // Close = Close
+ // Vol = Vol
+
+ /// <summary>
+ /// This opening value
+ /// </summary>
+ public double Open;
+
+ /// <summary>
+ /// This closing value
+ /// </summary>
+ public double Close;
+
+ /// <summary>
+ /// This daily trading volume
+ /// </summary>
+ public double Vol;
+
+ /// <summary>
+ /// This is a user value that can be anything. It is used to provide special
+ /// property-based coloration to the graph elements.
+ /// </summary>
+ private double _colorValue;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public StockPt() : this( 0, 0, 0, 0, 0, 0, null )
+ {
+ }
+
+ /// <summary>
+ /// Construct a new StockPt from the specified data values
+ /// </summary>
+ /// <param name="date">The trading date (<see cref="XDate" />)</param>
+ /// <param name="open">The opening stock price</param>
+ /// <param name="close">The closing stock price</param>
+ /// <param name="high">The daily high stock price</param>
+ /// <param name="low">The daily low stock price</param>
+ /// <param name="vol">The daily trading volume</param>
+ public StockPt( double date, double high, double low, double open, double close, double vol )
+ : this( date, high, low, open, close, vol, null )
+ {
+ }
+
+ /// <summary>
+ /// Construct a new StockPt from the specified data values including a Tag property
+ /// </summary>
+ /// <param name="date">The trading date (<see cref="XDate" />)</param>
+ /// <param name="open">The opening stock price</param>
+ /// <param name="close">The closing stock price</param>
+ /// <param name="high">The daily high stock price</param>
+ /// <param name="low">The daily low stock price</param>
+ /// <param name="vol">The daily trading volume</param>
+ /// <param name="tag">The user-defined <see cref="PointPair.Tag" /> property.</param>
+ public StockPt( double date, double high, double low, double open, double close, double vol,
+ string tag )
+ : base( date, high )
+ {
+ this.Low = low;
+ this.Open = open;
+ this.Close = close;
+ this.Vol = vol;
+ this.ColorValue = PointPair.Missing;
+ this.Tag = tag;
+ }
+
+ /// <summary>
+ /// The StockPt copy constructor.
+ /// </summary>
+ /// <param name="rhs">The basis for the copy.</param>
+ public StockPt( StockPt rhs )
+ : base( rhs )
+ {
+ this.Low = rhs.Low;
+ this.Open = rhs.Open;
+ this.Close = rhs.Close;
+ this.Vol = rhs.Vol;
+ this.ColorValue = rhs.ColorValue;
+
+ if ( rhs.Tag is ICloneable )
+ this.Tag = ( (ICloneable)rhs.Tag ).Clone();
+ else
+ this.Tag = rhs.Tag;
+ }
+
+ /// <summary>
+ /// The StockPt copy constructor.
+ /// </summary>
+ /// <param name="rhs">The basis for the copy.</param>
+ public StockPt( PointPair rhs )
+ : base( rhs )
+ {
+ if ( rhs is StockPt )
+ {
+ StockPt pt = rhs as StockPt;
+ this.Open = pt.Open;
+ this.Close = pt.Close;
+ this.Vol = pt.Vol;
+ this.ColorValue = rhs.ColorValue;
+ }
+ else
+ {
+ this.Open = PointPair.Missing;
+ this.Close = PointPair.Missing;
+ this.Vol = PointPair.Missing;
+ this.ColorValue = PointPair.Missing;
+ }
+ }
+
+ #endregion
+
+ #region Serialization
+
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema3 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected StockPt( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema3" );
+
+ Open = info.GetDouble( "Open" );
+ Close = info.GetDouble( "Close" );
+ Vol = info.GetDouble( "Vol" );
+ ColorValue = info.GetDouble( "ColorValue" );
+ }
+
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema3", schema2 );
+ info.AddValue( "Open", Open );
+ info.AddValue( "Close", Close );
+ info.AddValue( "Vol", Vol );
+ info.AddValue( "ColorValue", ColorValue );
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Map the Date property to the X value
+ /// </summary>
+ public double Date
+ {
+ get { return X; }
+ set { X = value; }
+ }
+
+ /// <summary>
+ /// Map the high property to the Y value
+ /// </summary>
+ public double High
+ {
+ get { return Y; }
+ set { Y = value; }
+ }
+
+ /// <summary>
+ /// Map the low property to the Z value
+ /// </summary>
+ public double Low
+ {
+ get { return Z; }
+ set { Z = value; }
+ }
+
+ /// <summary>
+ /// The ColorValue property. This is used with the
+ /// <see cref="FillType.GradientByColorValue" /> option.
+ /// </summary>
+ override public double ColorValue
+ {
+ get { return _colorValue; }
+ set { _colorValue = value; }
+ }
+
+ /// <summary>
+ /// Readonly value that determines if either the Date, Close, Open, High, or Low
+ /// coordinate in this StockPt is an invalid (not plotable) value.
+ /// It is considered invalid if it is missing (equal to System.Double.Max),
+ /// Infinity, or NaN.
+ /// </summary>
+ /// <returns>true if any value is invalid</returns>
+ public bool IsInvalid5D
+ {
+ get
+ {
+ return this.Date == PointPair.Missing ||
+ this.Close == PointPair.Missing ||
+ this.Open == PointPair.Missing ||
+ this.High == PointPair.Missing ||
+ this.Low == PointPair.Missing ||
+ Double.IsInfinity( this.Date ) ||
+ Double.IsInfinity( this.Close ) ||
+ Double.IsInfinity( this.Open ) ||
+ Double.IsInfinity( this.High ) ||
+ Double.IsInfinity( this.Low ) ||
+ Double.IsNaN( this.Date ) ||
+ Double.IsNaN( this.Close ) ||
+ Double.IsNaN( this.Open ) ||
+ Double.IsNaN( this.High ) ||
+ Double.IsNaN( this.Low );
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Format this StockPt value using the default format. Example: "( 12.345, -16.876 )".
+ /// The two double values are formatted with the "g" format type.
+ /// </summary>
+ /// <param name="isShowAll">true to show all the value coordinates</param>
+ /// <returns>A string representation of the <see cref="StockPt" />.</returns>
+ override public string ToString( bool isShowAll )
+ {
+ return this.ToString( PointPair.DefaultFormat, isShowAll );
+ }
+
+ /// <summary>
+ /// Format this PointPair value using a general format string.
+ /// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
+ /// If <see paramref="isShowAll"/>
+ /// is true, then the third all coordinates are shown.
+ /// </summary>
+ /// <param name="format">A format string that will be used to format each of
+ /// the two double type values (see <see cref="System.Double.ToString()"/>).</param>
+ /// <returns>A string representation of the PointPair</returns>
+ /// <param name="isShowAll">true to show all the value coordinates</param>
+ override public string ToString( string format, bool isShowAll )
+ {
+ return "( " + XDate.ToString( this.Date, "g" ) +
+ ", " + this.Close.ToString( format ) +
+ ( isShowAll ? (
+ ", " + this.Low.ToString( format ) +
+ ", " + this.Open.ToString( format ) +
+ ", " + this.Close.ToString( format ) ) : "" ) + " )";
+ }
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/Symbol.cs b/ZedGraph/Symbol.cs
new file mode 100644
index 0000000..75e1211
--- /dev/null
+++ b/ZedGraph/Symbol.cs
@@ -0,0 +1,679 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// This class handles the drawing of the curve <see cref="Symbol"/> objects.
+ /// The symbols are the small shapes that appear over each defined point
+ /// along the curve.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.37 $ $Date: 2007-09-19 06:41:56 $ </version>
+ [Serializable]
+ public class Symbol : ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary>
+ /// Private field that stores the size of this
+ /// <see cref="Symbol"/> in points (1/72 inch). Use the public
+ /// property <see cref="Size"/> to access this value.
+ /// </summary>
+ private float _size;
+ /// <summary>
+ /// Private field that stores the <see cref="SymbolType"/> for this
+ /// <see cref="Symbol"/>. Use the public
+ /// property <see cref="Type"/> to access this value.
+ /// </summary>
+ private SymbolType _type;
+ /// <summary>
+ /// private field that determines if the symbols are drawn using
+ /// Anti-Aliasing capabilities from the <see cref="Graphics" /> class.
+ /// Use the public property <see cref="IsAntiAlias" /> to access
+ /// this value.
+ /// </summary>
+ private bool _isAntiAlias;
+ /// <summary>
+ /// Private field that stores the visibility of this
+ /// <see cref="Symbol"/>. Use the public
+ /// property <see cref="IsVisible"/> to access this value. If this value is
+ /// false, the symbols will not be shown (but the <see cref="Line"/> may
+ /// still be shown).
+ /// </summary>
+ private bool _isVisible;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Symbol"/>. Use the public property <see cref="Fill"/> to
+ /// access this value.
+ /// </summary>
+ private Fill _fill;
+ /// <summary>
+ /// Private field that stores the <see cref="ZedGraph.Border"/> data for this
+ /// <see cref="Symbol"/>. Use the public property <see cref="Border"/> to
+ /// access this value.
+ /// </summary>
+ private Border _border;
+ /// <summary>
+ /// Private field that stores the user defined <see cref="GraphicsPath"/> data for this
+ /// <see cref="Symbol"/>. Use the public property <see cref="UserSymbol"/> to
+ /// access this value.
+ /// </summary>
+ private GraphicsPath _userSymbol;
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="ZedGraph.Symbol"/> class.
+ /// </summary>
+ public struct Default
+ {
+ // Default Symbol properties
+ /// <summary>
+ /// The default size for curve symbols (<see cref="Symbol.Size"/> property),
+ /// in units of points.
+ /// </summary>
+ public static float Size = 7;
+ /// <summary>
+ /// The default pen width to be used for drawing curve symbols
+ /// (<see cref="ZedGraph.LineBase.Width"/> property). Units are points.
+ /// </summary>
+ public static float PenWidth = 1.0F;
+ /// <summary>
+ /// The default color for filling in this <see cref="Symbol"/>
+ /// (<see cref="ZedGraph.Fill.Color"/> property).
+ /// </summary>
+ public static Color FillColor = Color.Red;
+ /// <summary>
+ /// The default custom brush for filling in this <see cref="Symbol"/>
+ /// (<see cref="ZedGraph.Fill.Brush"/> property).
+ /// </summary>
+ public static Brush FillBrush = null;
+ /// <summary>
+ /// The default fill mode for the curve (<see cref="ZedGraph.Fill.Type"/> property).
+ /// </summary>
+ public static FillType FillType = FillType.None;
+ /// <summary>
+ /// The default symbol type for curves (<see cref="Symbol.Type"/> property).
+ /// This is defined as a <see cref="ZedGraph.SymbolType"/> enumeration.
+ /// </summary>
+ public static SymbolType Type = SymbolType.Square;
+ /// <summary>
+ /// The default value for the <see cref="Symbol.IsAntiAlias"/>
+ /// property.
+ /// </summary>
+ public static bool IsAntiAlias = false;
+ /// <summary>
+ /// The default display mode for symbols (<see cref="Symbol.IsVisible"/> property).
+ /// true to display symbols, false to hide them.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// The default for drawing frames around symbols (<see cref="ZedGraph.LineBase.IsVisible"/> property).
+ /// true to display symbol frames, false to hide them.
+ /// </summary>
+ public static bool IsBorderVisible = true;
+ /// <summary>
+ /// The default color for drawing symbols (<see cref="ZedGraph.LineBase.Color"/> property).
+ /// </summary>
+ public static Color BorderColor = Color.Red;
+ }
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets or sets the size of the <see cref="Symbol"/>
+ /// </summary>
+ /// <value>Size in points (1/72 inch)</value>
+ /// <seealso cref="Default.Size"/>
+ public float Size
+ {
+ get { return _size; }
+ set { _size = value; }
+ }
+ /// <summary>
+ /// Gets or sets the type (shape) of the <see cref="Symbol"/>
+ /// </summary>
+ /// <value>A <see cref="SymbolType"/> enum value indicating the shape</value>
+ /// <seealso cref="Default.Type"/>
+ public SymbolType Type
+ {
+ get { return _type; }
+ set { _type = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines if the symbols are drawn using
+ /// Anti-Aliasing capabilities from the <see cref="Graphics" /> class.
+ /// </summary>
+ /// <remarks>
+ /// If this value is set to true, then the <see cref="Graphics.SmoothingMode" />
+ /// property will be set to <see cref="SmoothingMode.HighQuality" /> only while
+ /// this <see cref="Symbol" /> is drawn. A value of false will leave the value of
+ /// <see cref="Graphics.SmoothingMode" /> unchanged.
+ /// </remarks>
+ public bool IsAntiAlias
+ {
+ get { return _isAntiAlias; }
+ set { _isAntiAlias = value; }
+ }
+ /// <summary>
+ /// Gets or sets a property that shows or hides the <see cref="Symbol"/>.
+ /// </summary>
+ /// <value>true to show the symbol, false to hide it</value>
+ /// <seealso cref="Default.IsVisible"/>
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set { _isVisible = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Fill"/> data for this
+ /// <see cref="Symbol"/>.
+ /// </summary>
+ public Fill Fill
+ {
+ get { return _fill; }
+ set { _fill = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.Border"/> data for this
+ /// <see cref="Symbol"/>, which controls the border outline of the symbol.
+ /// </summary>
+ public Border Border
+ {
+ get { return _border; }
+ set { _border = value; }
+ }
+ /// <summary>
+ /// Gets or sets the <see cref="GraphicsPath"/> data for this
+ /// <see cref="Symbol"/>, describing the user-defined symbol type.
+ /// </summary>
+ /// <remarks>
+ /// This value only applies if <see cref="Symbol.Type">Symbol.Type</see>
+ /// is <see cref="SymbolType.UserDefined">SymbolType.UserDefined</see>
+ /// </remarks>
+ public GraphicsPath UserSymbol
+ {
+ get { return _userSymbol; }
+ set { _userSymbol = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Default constructor that sets all <see cref="Symbol"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ public Symbol() : this( SymbolType.Default, Color.Empty )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets the <see cref="SymbolType"/> and
+ /// <see cref="Color"/> as specified, and the remaining
+ /// <see cref="Symbol"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="type">A <see cref="SymbolType"/> enum value
+ /// indicating the shape of the symbol</param>
+ /// <param name="color">A <see cref="Color"/> value indicating
+ /// the color of the symbol
+ /// </param>
+ public Symbol( SymbolType type, Color color )
+ {
+ _size = Default.Size;
+ _type = type;
+ _isAntiAlias = Default.IsAntiAlias;
+ _isVisible = Default.IsVisible;
+ _border = new Border( Default.IsBorderVisible, color, Default.PenWidth );
+ _fill = new Fill( color, Default.FillBrush, Default.FillType );
+ _userSymbol = null;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The Symbol object from which to copy</param>
+ public Symbol( Symbol rhs )
+ {
+ _size = rhs.Size;
+ _type = rhs.Type;
+ _isAntiAlias = rhs._isAntiAlias;
+ _isVisible = rhs.IsVisible;
+ _fill = rhs.Fill.Clone();
+ _border = rhs.Border.Clone();
+
+ if ( rhs.UserSymbol != null )
+ _userSymbol = rhs.UserSymbol.Clone() as GraphicsPath;
+ else
+ _userSymbol = null;
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Symbol Clone()
+ {
+ return new Symbol( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Symbol( SerializationInfo info, StreamingContext context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema" );
+
+ _size = info.GetSingle( "size" );
+ _type = (SymbolType) info.GetValue( "type", typeof(SymbolType) );
+ _isAntiAlias = info.GetBoolean( "isAntiAlias" );
+ _isVisible = info.GetBoolean( "isVisible" );
+ _fill = (Fill) info.GetValue( "fill", typeof(Fill) );
+ _border = (Border) info.GetValue( "border", typeof(Border) );
+
+ if ( sch >= 11 )
+ _userSymbol = (GraphicsPath)info.GetValue( "userSymbol", typeof( GraphicsPath ) );
+ else
+ _userSymbol = null;
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ info.AddValue( "schema", schema );
+ info.AddValue( "size", _size );
+ info.AddValue( "type", _type );
+ info.AddValue( "isAntiAlias", _isAntiAlias );
+ info.AddValue( "isVisible", _isVisible );
+ info.AddValue( "fill", _fill );
+ info.AddValue( "border", _border );
+ info.AddValue( "userSymbol", _userSymbol );
+ }
+ #endregion
+
+ #region Rendering Methods
+
+ /// <summary>
+ /// Draw the <see cref="Symbol"/> to the specified <see cref="Graphics"/> device
+ /// at the specified location. This routine draws a single symbol.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="x">The x position of the center of the symbol in
+ /// pixel units</param>
+ /// <param name="y">The y position of the center of the symbol in
+ /// pixel units</param>
+ /// <param name="path">A <see cref="GraphicsPath"/> previously constructed by
+ /// <see cref="MakePath"/> for this symbol</param>
+ /// <param name="pen">A <see cref="Pen"/> class representing the standard pen for this symbol</param>
+ /// <param name="brush">A <see cref="Brush"/> class representing a default solid brush for this symbol
+ /// If this symbol uses a <see cref="LinearGradientBrush"/>, it will be created on the fly for
+ /// each point, since it has to be scaled to the individual point coordinates.</param>
+ private void DrawSymbol( Graphics g, int x, int y, GraphicsPath path,
+ Pen pen, Brush brush )
+ {
+ // Only draw if the symbol is visible
+ if ( _isVisible &&
+ this.Type != SymbolType.None &&
+ x < 100000 && x > -100000 &&
+ y < 100000 && y > -100000 )
+ {
+ Matrix saveMatrix = g.Transform;
+ g.TranslateTransform( x, y );
+
+ // Fill or draw the symbol as required
+ if ( _fill.IsVisible )
+ g.FillPath( brush, path );
+ //FillPoint( g, x, y, scaleFactor, pen, brush );
+
+ if ( _border.IsVisible )
+ g.DrawPath( pen, path );
+ //DrawPoint( g, x, y, scaleFactor, pen );
+
+ g.Transform = saveMatrix;
+ }
+ }
+
+ /// <summary>
+ /// Draw the <see cref="Symbol"/> to the specified <see cref="Graphics"/> device
+ /// at the specified location. This routine draws a single symbol.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="x">The x position of the center of the symbol in
+ /// pixel units</param>
+ /// <param name="y">The y position of the center of the symbol in
+ /// pixel units</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
+ /// </param>
+ /// <param name="dataValue">The data value to be used for a value-based
+ /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>,
+ /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param>
+ /// <param name="isSelected">Indicates that the <see cref="Symbol" /> should be drawn
+ /// with attributes from the <see cref="Selection" /> class.
+ /// </param>
+ public void DrawSymbol( Graphics g, GraphPane pane, int x, int y,
+ float scaleFactor, bool isSelected, PointPair dataValue )
+ {
+ Symbol source = this;
+ if ( isSelected )
+ source = Selection.Symbol;
+
+ // Only draw if the symbol is visible
+ if ( _isVisible &&
+ this.Type != SymbolType.None &&
+ x < 100000 && x > -100000 &&
+ y < 100000 && y > -100000 )
+ {
+ SmoothingMode sModeSave = g.SmoothingMode;
+ if ( _isAntiAlias )
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ using ( Pen pen = _border.GetPen( pane, scaleFactor, dataValue ) )
+ using ( GraphicsPath path = this.MakePath( g, scaleFactor ) )
+ using ( Brush brush = this.Fill.MakeBrush( path.GetBounds(), dataValue ) )
+ {
+ DrawSymbol( g, x, y, path, pen, brush );
+ }
+
+ g.SmoothingMode = sModeSave;
+ }
+ }
+
+ /// <summary>
+ /// Create a <see cref="GraphicsPath"/> struct for the current symbol based on the
+ /// specified scaleFactor and assuming the symbol will be centered at position 0,0.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This
+ /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor
+ /// represents a linear multiple to be applied to font sizes, symbol sizes, etc.</param>
+ /// <returns>Returns the <see cref="GraphicsPath"/> for the current symbol</returns>
+ public GraphicsPath MakePath( Graphics g, float scaleFactor )
+ {
+ float scaledSize = (float) ( _size * scaleFactor );
+ float hsize = scaledSize / 2,
+ hsize1 = hsize + 1;
+
+ GraphicsPath path = new GraphicsPath();
+
+ switch( _type == SymbolType.Default || ( _type == SymbolType.UserDefined && _userSymbol == null ) ? Default.Type : _type )
+ {
+ case SymbolType.Square:
+ path.AddLine( -hsize, -hsize, hsize, -hsize );
+ path.AddLine( hsize, -hsize, hsize, hsize );
+ path.AddLine( hsize, hsize, -hsize, hsize );
+ path.AddLine( -hsize, hsize, -hsize, -hsize );
+ break;
+ case SymbolType.Diamond:
+ path.AddLine( 0, -hsize, hsize, 0 );
+ path.AddLine( hsize, 0, 0, hsize );
+ path.AddLine( 0, hsize, -hsize, 0 );
+ path.AddLine( -hsize, 0, 0, -hsize );
+ break;
+ case SymbolType.Triangle:
+ path.AddLine( 0, -hsize, hsize, hsize );
+ path.AddLine( hsize, hsize, -hsize, hsize );
+ path.AddLine( -hsize, hsize, 0, -hsize );
+ break;
+ case SymbolType.Circle:
+ path.AddEllipse( -hsize, -hsize, scaledSize, scaledSize );
+ break;
+ case SymbolType.XCross:
+ path.AddLine( -hsize, -hsize, hsize1, hsize1 );
+ path.StartFigure();
+ path.AddLine( hsize, -hsize, -hsize1, hsize1 );
+ break;
+ case SymbolType.Plus:
+ path.AddLine( 0, -hsize, 0, hsize1 );
+ path.StartFigure();
+ path.AddLine( -hsize, 0, hsize1, 0 );
+ break;
+ case SymbolType.Star:
+ path.AddLine( 0, -hsize, 0, hsize1 );
+ path.StartFigure();
+ path.AddLine( -hsize, 0, hsize1, 0 );
+ path.StartFigure();
+ path.AddLine( -hsize, -hsize, hsize1, hsize1 );
+ path.StartFigure();
+ path.AddLine( hsize, -hsize, -hsize1, hsize1 );
+ break;
+ case SymbolType.TriangleDown:
+ path.AddLine( 0, hsize, hsize, -hsize );
+ path.AddLine( hsize, -hsize, -hsize, -hsize );
+ path.AddLine( -hsize, -hsize, 0, hsize );
+ break;
+ case SymbolType.HDash:
+ path.AddLine( -hsize, 0, hsize1, 0 );
+ break;
+ case SymbolType.VDash:
+ path.AddLine( 0, -hsize, 0, hsize1 );
+ break;
+ case SymbolType.UserDefined:
+ path = _userSymbol.Clone() as GraphicsPath;
+ Matrix scaleTransform = new Matrix( scaledSize, 0.0f, 0.0f, scaledSize, 0.0f, 0.0f );
+ path.Transform( scaleTransform );
+ break;
+ }
+
+ return path;
+ }
+
+ /// <summary>
+ /// Draw this <see cref="CurveItem"/> to the specified <see cref="Graphics"/>
+ /// device as a symbol at each defined point. The routine
+ /// only draws the symbols; the lines are draw by the
+ /// <see cref="Line.DrawCurve"/> method. This method
+ /// is normally only called by the Draw method of the
+ /// <see cref="CurveItem"/> object
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="curve">A <see cref="LineItem"/> representing this
+ /// curve.</param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <param name="isSelected">Indicates that the <see cref="Symbol" /> should be drawn
+ /// with attributes from the <see cref="Selection" /> class.
+ /// </param>
+ public void Draw( Graphics g, GraphPane pane, LineItem curve, float scaleFactor,
+ bool isSelected )
+ {
+ Symbol source = this;
+ if ( isSelected )
+ source = Selection.Symbol;
+
+ int tmpX, tmpY;
+
+ int minX = (int)pane.Chart.Rect.Left;
+ int maxX = (int)pane.Chart.Rect.Right;
+ int minY = (int)pane.Chart.Rect.Top;
+ int maxY = (int)pane.Chart.Rect.Bottom;
+
+ // (Dale-a-b) we'll set an element to true when it has been drawn
+ bool[,] isPixelDrawn = new bool[maxX + 1, maxY + 1];
+
+ double curX, curY, lowVal;
+ IPointList points = curve.Points;
+
+ if ( points != null && ( _border.IsVisible || _fill.IsVisible ) )
+ {
+ SmoothingMode sModeSave = g.SmoothingMode;
+ if ( _isAntiAlias )
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ // For the sake of speed, go ahead and create a solid brush and a pen
+ // If it's a gradient fill, it will be created on the fly for each symbol
+ //SolidBrush brush = new SolidBrush( this.fill.Color );
+
+ using ( Pen pen = source._border.GetPen( pane, scaleFactor ) )
+ using ( GraphicsPath path = MakePath( g, scaleFactor ) )
+ {
+ RectangleF rect = path.GetBounds();
+
+ using ( Brush brush = source.Fill.MakeBrush( rect ) )
+ {
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ Scale xScale = curve.GetXAxis( pane ).Scale;
+ Scale yScale = curve.GetYAxis( pane ).Scale;
+
+ bool xIsLog = xScale.IsLog;
+ bool yIsLog = yScale.IsLog;
+ bool xIsOrdinal = xScale.IsAnyOrdinal;
+
+ double xMin = xScale.Min;
+ double xMax = xScale.Max;
+
+ // Loop over each defined point
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ // Get the user scale values for the current point
+ // use the valueHandler only for stacked types
+ if ( pane.LineType == LineType.Stack )
+ {
+ valueHandler.GetValues( curve, i, out curX, out lowVal, out curY );
+ }
+ // otherwise, just access the values directly. Avoiding the valueHandler for
+ // non-stacked types is an optimization to minimize overhead in case there are
+ // a large number of points.
+ else
+ {
+ curX = points[i].X;
+ if ( curve is StickItem )
+ curY = points[i].Z;
+ else
+ curY = points[i].Y;
+ }
+
+ // Any value set to double max is invalid and should be skipped
+ // This is used for calculated values that are out of range, divide
+ // by zero, etc.
+ // Also, any value <= zero on a log scale is invalid
+
+ if ( curX != PointPair.Missing &&
+ curY != PointPair.Missing &&
+ !System.Double.IsNaN( curX ) &&
+ !System.Double.IsNaN( curY ) &&
+ !System.Double.IsInfinity( curX ) &&
+ !System.Double.IsInfinity( curY ) &&
+ ( curX > 0 || !xIsLog ) &&
+ ( !yIsLog || curY > 0.0 ) &&
+ ( xIsOrdinal || ( curX >= xMin && curX <= xMax ) ) )
+ {
+ // Transform the user scale values to pixel locations
+ tmpX = (int) xScale.Transform( curve.IsOverrideOrdinal, i, curX );
+ tmpY = (int) yScale.Transform( curve.IsOverrideOrdinal, i, curY );
+
+ // Maintain an array of "used" pixel locations to avoid duplicate drawing operations
+ if ( tmpX >= minX && tmpX <= maxX && tmpY >= minY && tmpY <= maxY ) // guard against the zoom-in case
+ {
+ if ( isPixelDrawn[tmpX, tmpY] )
+ continue;
+ isPixelDrawn[tmpX, tmpY] = true;
+ }
+
+ // If the fill type for this symbol is a Gradient by value type,
+ // the make a brush corresponding to the appropriate current value
+ if ( _fill.IsGradientValueType || _border._gradientFill.IsGradientValueType )
+ {
+ using ( Brush tBrush = _fill.MakeBrush( rect, points[i] ) )
+ using ( Pen tPen = _border.GetPen( pane, scaleFactor, points[i] ) )
+ this.DrawSymbol( g, tmpX, tmpY, path, tPen, tBrush );
+ }
+ else
+ {
+ // Otherwise, the brush is already defined
+ // Draw the symbol at the specified pixel location
+ this.DrawSymbol( g, tmpX, tmpY, path, pen, brush );
+ }
+ }
+ }
+ }
+ }
+
+ g.SmoothingMode = sModeSave;
+ }
+ }
+ #endregion
+
+ }
+}
+
diff --git a/ZedGraph/TextObj.cs b/ZedGraph/TextObj.cs
new file mode 100644
index 0000000..96caa67
--- /dev/null
+++ b/ZedGraph/TextObj.cs
@@ -0,0 +1,446 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that represents a text object on the graph. A list of
+ /// <see cref="GraphObj"/> objects is maintained by the
+ /// <see cref="GraphObjList"/> collection class.
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.4 $ $Date: 2007-01-25 07:56:09 $ </version>
+ [Serializable]
+ public class TextObj : GraphObj, ICloneable, ISerializable
+ {
+ #region Fields
+ /// <summary> Private field to store the actual text string for this
+ /// <see cref="TextObj"/>. Use the public property <see cref="TextObj.Text"/>
+ /// to access this value.
+ /// </summary>
+ private string _text;
+ /// <summary>
+ /// Private field to store the <see cref="FontSpec"/> class used to render
+ /// this <see cref="TextObj"/>. Use the public property <see cref="FontSpec"/>
+ /// to access this class.
+ /// </summary>
+ private FontSpec _fontSpec;
+
+ /*
+ /// <summary>
+ /// Private field to indicate whether this <see cref="TextObj"/> is to be
+ /// wrapped when rendered. Wrapping is to be done within <see cref="TextObj.wrappedRect"/>.
+ /// Use the public property <see cref="TextObj.IsWrapped"/>
+ /// to access this value.
+ /// </summary>
+ private bool isWrapped;
+ */
+
+ /// <summary>
+ /// Private field holding the SizeF into which this <see cref="TextObj"/>
+ /// should be rendered. Use the public property <see cref="TextObj.LayoutArea"/>
+ /// to access this value.
+ /// </summary>
+ private SizeF _layoutArea;
+
+
+ #endregion
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="TextObj"/> class.
+ /// </summary>
+ new public struct Default
+ {
+ /*
+ /// <summary>
+ /// The default wrapped flag for rendering this <see cref="TextObj,Text"/>.
+ /// </summary>
+ public static bool IsWrapped = false ;
+ /// <summary>
+ /// The default RectangleF for rendering this <see cref="TextObj.Text"/>
+ /// </summary>
+ public static SizeF WrappedSize = new SizeF( 0,0 );
+ */
+
+ /// <summary>
+ /// The default font family for the <see cref="TextObj"/> text
+ /// (<see cref="ZedGraph.FontSpec.Family"/> property).
+ /// </summary>
+ public static string FontFamily = "Arial";
+ /// <summary>
+ /// The default font size for the <see cref="TextObj"/> text
+ /// (<see cref="ZedGraph.FontSpec.Size"/> property). Units are
+ /// in points (1/72 inch).
+ /// </summary>
+ public static float FontSize = 12.0F;
+ /// <summary>
+ /// The default font color for the <see cref="TextObj"/> text
+ /// (<see cref="ZedGraph.FontSpec.FontColor"/> property).
+ /// </summary>
+ public static Color FontColor = Color.Black;
+ /// <summary>
+ /// The default font bold mode for the <see cref="TextObj"/> text
+ /// (<see cref="ZedGraph.FontSpec.IsBold"/> property). true
+ /// for a bold typeface, false otherwise.
+ /// </summary>
+ public static bool FontBold = false;
+ /// <summary>
+ /// The default font underline mode for the <see cref="TextObj"/> text
+ /// (<see cref="ZedGraph.FontSpec.IsUnderline"/> property). true
+ /// for an underlined typeface, false otherwise.
+ /// </summary>
+ public static bool FontUnderline = false;
+ /// <summary>
+ /// The default font italic mode for the <see cref="TextObj"/> text
+ /// (<see cref="ZedGraph.FontSpec.IsItalic"/> property). true
+ /// for an italic typeface, false otherwise.
+ /// </summary>
+ public static bool FontItalic = false;
+ }
+ #endregion
+
+ #region Properties
+
+ /*
+ /// <summary>
+ ///
+ /// </summary>
+ internal bool IsWrapped
+ {
+ get { return (this.isWrapped); }
+ set { this.isWrapped = value; }
+ }
+ */
+
+ /// <summary>
+ ///
+ /// </summary>
+ public SizeF LayoutArea
+ {
+ get { return _layoutArea; }
+ set { _layoutArea = value; }
+ }
+
+
+ /// <summary>
+ /// The <see cref="TextObj"/> to be displayed. This text can be multi-line by
+ /// including newline ('\n') characters between the lines.
+ /// </summary>
+ public string Text
+ {
+ get { return _text; }
+ set { _text = value; }
+ }
+ /// <summary>
+ /// Gets a reference to the <see cref="FontSpec"/> class used to render
+ /// this <see cref="TextObj"/>
+ /// </summary>
+ /// <seealso cref="Default.FontColor"/>
+ /// <seealso cref="Default.FontBold"/>
+ /// <seealso cref="Default.FontItalic"/>
+ /// <seealso cref="Default.FontUnderline"/>
+ /// <seealso cref="Default.FontFamily"/>
+ /// <seealso cref="Default.FontSize"/>
+ public FontSpec FontSpec
+ {
+ get { return _fontSpec; }
+ set
+ {
+ if ( value == null )
+ throw new ArgumentNullException( "Uninitialized FontSpec in TextObj" );
+ _fontSpec = value;
+ }
+ }
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Constructor that sets all <see cref="TextObj"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="text">The text to be displayed.</param>
+ /// <param name="x">The x position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the <see cref="AlignH"/>
+ /// property.</param>
+ /// <param name="y">The y position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the
+ /// <see cref="AlignV"/> property.</param>
+ public TextObj( string text, double x, double y )
+ : base( x, y )
+ {
+ Init( text );
+ }
+
+ private void Init( string text )
+ {
+ if ( text != null )
+ _text = text;
+ else
+ text = "Text";
+
+ _fontSpec = new FontSpec(
+ Default.FontFamily, Default.FontSize,
+ Default.FontColor, Default.FontBold,
+ Default.FontItalic, Default.FontUnderline );
+
+ //this.isWrapped = Default.IsWrapped ;
+ _layoutArea = new SizeF( 0, 0 );
+ }
+
+ /// <summary>
+ /// Constructor that sets all <see cref="TextObj"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="text">The text to be displayed.</param>
+ /// <param name="x">The x position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the <see cref="AlignH"/>
+ /// property.</param>
+ /// <param name="y">The y position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the
+ /// <see cref="AlignV"/> property.</param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum value that
+ /// indicates what type of coordinate system the x and y parameters are
+ /// referenced to.</param>
+ public TextObj( string text, double x, double y, CoordType coordType )
+ : base( x, y, coordType )
+ {
+ Init( text );
+ }
+
+ /// <summary>
+ /// Constructor that sets all <see cref="TextObj"/> properties to default
+ /// values as defined in the <see cref="Default"/> class.
+ /// </summary>
+ /// <param name="text">The text to be displayed.</param>
+ /// <param name="x">The x position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the <see cref="AlignH"/>
+ /// property.</param>
+ /// <param name="y">The y position of the text. The units
+ /// of this position are specified by the
+ /// <see cref="ZedGraph.Location.CoordinateFrame"/> property. The text will be
+ /// aligned to this position based on the
+ /// <see cref="AlignV"/> property.</param>
+ /// <param name="coordType">The <see cref="CoordType"/> enum value that
+ /// indicates what type of coordinate system the x and y parameters are
+ /// referenced to.</param>
+ /// <param name="alignH">The <see cref="ZedGraph.AlignH"/> enum that specifies
+ /// the horizontal alignment of the object with respect to the (x,y) location</param>
+ /// <param name="alignV">The <see cref="ZedGraph.AlignV"/> enum that specifies
+ /// the vertical alignment of the object with respect to the (x,y) location</param>
+ public TextObj( string text, double x, double y, CoordType coordType, AlignH alignH, AlignV alignV )
+ : base( x, y, coordType, alignH, alignV )
+ {
+ Init( text );
+ }
+
+ /// <summary>
+ /// Parameterless constructor that initializes a new <see cref="TextObj"/>.
+ /// </summary>
+ public TextObj() : base( 0, 0 )
+ {
+ Init( "" );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="TextObj"/> object from which to copy</param>
+ public TextObj( TextObj rhs ) : base( rhs )
+ {
+ _text = rhs.Text;
+ _fontSpec = new FontSpec( rhs.FontSpec );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public TextObj Clone()
+ {
+ return new TextObj( this );
+ }
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected TextObj( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ _text = info.GetString( "text" );
+ _fontSpec = (FontSpec) info.GetValue( "fontSpec", typeof(FontSpec) );
+ //isWrapped = info.GetBoolean ("isWrapped") ;
+ _layoutArea = (SizeF) info.GetValue( "layoutArea", typeof(SizeF) );
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ info.AddValue( "text", _text );
+ info.AddValue( "fontSpec", _fontSpec );
+ //info.AddValue( "isWrapped", isWrapped );
+ info.AddValue( "layoutArea", _layoutArea );
+ }
+ #endregion
+
+ #region Rendering Methods
+ /// <summary>
+ /// Render this <see cref="TextObj"/> object to the specified <see cref="Graphics"/> device
+ /// This method is normally only called by the Draw method
+ /// of the parent <see cref="GraphObjList"/> collection object.
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void Draw( Graphics g, PaneBase pane, float scaleFactor )
+ {
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ PointF pix = _location.Transform( pane );
+
+ // Draw the text on the screen, including any frame and background
+ // fill elements
+ if ( pix.X > -100000 && pix.X < 100000 && pix.Y > -100000 && pix.Y < 100000 )
+ {
+ //if ( this.layoutSize.IsEmpty )
+ // this.FontSpec.Draw( g, pane.IsPenWidthScaled, this.text, pix.X, pix.Y,
+ // this.location.AlignH, this.location.AlignV, scaleFactor );
+ //else
+ this.FontSpec.Draw( g, pane, _text, pix.X, pix.Y,
+ _location.AlignH, _location.AlignV, scaleFactor, _layoutArea );
+
+ }
+ }
+
+ /// <summary>
+ /// Determine if the specified screen point lies inside the bounding box of this
+ /// <see cref="TextObj"/>. This method takes into account rotation and alignment
+ /// parameters of the text, as specified in the <see cref="FontSpec"/>.
+ /// </summary>
+ /// <param name="pt">The screen point, in pixels</param>
+ /// <param name="pane">
+ /// A reference to the <see cref="PaneBase"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <returns>true if the point lies in the bounding box, false otherwise</returns>
+ override public bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor )
+ {
+ if ( ! base.PointInBox(pt, pane, g, scaleFactor ) )
+ return false;
+
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ PointF pix = _location.Transform( pane );
+
+ return _fontSpec.PointInBox( pt, g, _text, pix.X, pix.Y,
+ _location.AlignH, _location.AlignV, scaleFactor, this.LayoutArea );
+ }
+
+ /// <summary>
+ /// Determines the shape type and Coords values for this GraphObj
+ /// </summary>
+ override public void GetCoords( PaneBase pane, Graphics g, float scaleFactor,
+ out string shape, out string coords )
+ {
+ // transform the x,y location from the user-defined
+ // coordinate frame to the screen pixel location
+ PointF pix = _location.Transform( pane );
+
+ PointF[] pts = _fontSpec.GetBox( g, _text, pix.X, pix.Y, _location.AlignH,
+ _location.AlignV, scaleFactor, new SizeF() );
+
+ shape = "poly";
+ coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0},{4:f0},{5:f0},{6:f0},{7:f0},",
+ pts[0].X, pts[0].Y, pts[1].X, pts[1].Y,
+ pts[2].X, pts[2].Y, pts[3].X, pts[3].Y );
+ }
+
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/TextScale.cs b/ZedGraph/TextScale.cs
new file mode 100644
index 0000000..2e0e1a3
--- /dev/null
+++ b/ZedGraph/TextScale.cs
@@ -0,0 +1,327 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// The TextScale class inherits from the <see cref="Scale" /> class, and implements
+ /// the features specific to <see cref="AxisType.Text" />.
+ /// </summary>
+ /// <remarks>
+ /// TextScale is an ordinal axis with user-defined text labels. An ordinal axis means that
+ /// all data points are evenly spaced at integral values, and the actual coordinate values
+ /// for points corresponding to that axis are ignored. That is, if the X axis is an
+ /// ordinal type, then all X values associated with the curves are ignored.
+ /// </remarks>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 1.8 $ $Date: 2006-08-25 05:19:09 $ </version>
+ [Serializable]
+ class TextScale : Scale, ISerializable //, ICloneable
+ {
+
+ #region constructors
+
+ public TextScale( Axis owner )
+ : base( owner )
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="TextScale" /> object from which to copy</param>
+ /// <param name="owner">The <see cref="Axis" /> object that will own the
+ /// new instance of <see cref="TextScale" /></param>
+ public TextScale( Scale rhs, Axis owner )
+ : base( rhs, owner )
+ {
+ }
+
+ /// <summary>
+ /// Create a new clone of the current item, with a new owner assignment
+ /// </summary>
+ /// <param name="owner">The new <see cref="Axis" /> instance that will be
+ /// the owner of the new Scale</param>
+ /// <returns>A new <see cref="Scale" /> clone.</returns>
+ public override Scale Clone( Axis owner )
+ {
+ return new TextScale( this, owner );
+ }
+
+ #endregion
+
+ #region properties
+
+ public override AxisType Type
+ {
+ get { return AxisType.Text; }
+ }
+
+ #endregion
+
+ #region methods
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first minor tic mark
+ /// </summary>
+ /// <param name="baseVal">
+ /// The value of the first major tic for the axis.
+ /// </param>
+ /// <returns>
+ /// The ordinal position of the first minor tic, relative to the first major tic.
+ /// This value can be negative (e.g., -3 means the first minor tic is 3 minor step
+ /// increments before the first major tic.
+ /// </returns>
+ override internal int CalcMinorStart( double baseVal )
+ {
+ // This should never happen (no minor tics for text labels)
+ return 0;
+ }
+
+ /// <summary>
+ /// Determine the value for the first major tic.
+ /// </summary>
+ /// <remarks>
+ /// This is done by finding the first possible value that is an integral multiple of
+ /// the step size, taking into account the date/time units if appropriate.
+ /// This method properly accounts for <see cref="Scale.IsLog"/>, <see cref="Scale.IsText"/>,
+ /// and other axis format settings.
+ /// </remarks>
+ /// <returns>
+ /// First major tic value (floating point double).
+ /// </returns>
+ override internal double CalcBaseTic()
+ {
+ if ( _baseTic != PointPair.Missing )
+ return _baseTic;
+ else
+ return 1.0;
+
+ }
+
+ /// <summary>
+ /// Internal routine to determine the ordinals of the first and last major axis label.
+ /// </summary>
+ /// <returns>
+ /// This is the total number of major tics for this axis.
+ /// </returns>
+ override internal int CalcNumTics()
+ {
+ int nTics = 1;
+
+ // If no array of labels is available, just assume 10 labels so we don't blow up.
+ if ( _textLabels == null )
+ nTics = 10;
+ else
+ nTics = _textLabels.Length;
+
+ if ( nTics < 1 )
+ nTics = 1;
+ else if ( nTics > 1000 )
+ nTics = 1000;
+
+ return nTics;
+ }
+
+ /// <summary>
+ /// Select a reasonable text axis scale given a range of data values.
+ /// </summary>
+ /// <remarks>
+ /// This method only applies to <see cref="AxisType.Text"/> type axes, and it
+ /// is called by the general <see cref="PickScale"/> method. This is an ordinal
+ /// type, such that the labeled values start at 1.0 and increment by 1.0 for
+ /// each successive label. The maximum number of labels on the graph is
+ /// determined by <see cref="Scale.Default.MaxTextLabels"/>. If necessary, this method will
+ /// set the <see cref="Scale.MajorStep"/> value to greater than 1.0 in order to keep the total
+ /// labels displayed below <see cref="Scale.Default.MaxTextLabels"/>. For example, a
+ /// <see cref="Scale.MajorStep"/> size of 2.0 would only display every other label on the
+ /// axis. The <see cref="Scale.MajorStep"/> value calculated by this routine is always
+ /// an integral value. This
+ /// method honors the <see cref="Scale.MinAuto"/>, <see cref="Scale.MaxAuto"/>,
+ /// and <see cref="Scale.MajorStepAuto"/> autorange settings.
+ /// In the event that any of the autorange settings are false, the
+ /// corresponding <see cref="Scale.Min"/>, <see cref="Scale.Max"/>, or <see cref="Scale.MajorStep"/>
+ /// setting is explicitly honored, and the remaining autorange settings (if any) will
+ /// be calculated to accomodate the non-autoranged values.
+ /// <para>On Exit:</para>
+ /// <para><see cref="Scale.Min"/> is set to scale minimum (if <see cref="Scale.MinAuto"/> = true)</para>
+ /// <para><see cref="Scale.Max"/> is set to scale maximum (if <see cref="Scale.MaxAuto"/> = true)</para>
+ /// <para><see cref="Scale.MajorStep"/> is set to scale step size (if <see cref="Scale.MajorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.MinorStep"/> is set to scale minor step size (if <see cref="Scale.MinorStepAuto"/> = true)</para>
+ /// <para><see cref="Scale.Mag"/> is set to a magnitude multiplier according to the data</para>
+ /// <para><see cref="Scale.Format"/> is set to the display format for the values (this controls the
+ /// number of decimal places, whether there are thousands separators, currency types, etc.)</para>
+ /// </remarks>
+ /// <param name="pane">A reference to the <see cref="GraphPane"/> object
+ /// associated with this <see cref="Axis"/></param>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ /// <seealso cref="PickScale"/>
+ /// <seealso cref="AxisType.Text"/>
+ override public void PickScale( GraphPane pane, Graphics g, float scaleFactor )
+ {
+ // call the base class first
+ base.PickScale( pane, g, scaleFactor );
+
+ // if text labels are provided, then autorange to the number of labels
+ if ( _textLabels != null )
+ {
+ if ( _minAuto )
+ _min = 0.5;
+ if ( _maxAuto )
+ _max = _textLabels.Length + 0.5;
+ }
+ else
+ {
+ if ( _minAuto )
+ _min -= 0.5;
+ if ( _maxAuto )
+ _max += 0.5;
+ }
+ // Test for trivial condition of range = 0 and pick a suitable default
+ if ( _max - _min < .1 )
+ {
+ if ( _maxAuto )
+ _max = _min + 10.0;
+ else
+ _min = _max - 10.0;
+ }
+
+ if ( _majorStepAuto )
+ {
+ if ( !_isPreventLabelOverlap )
+ {
+ _majorStep = 1;
+ }
+ else if ( _textLabels != null )
+ {
+ // Calculate the maximum number of labels
+ double maxLabels = (double) this.CalcMaxLabels( g, pane, scaleFactor );
+
+ // Calculate a step size based on the width of the labels
+ double tmpStep = Math.Ceiling( ( _max - _min ) / maxLabels );
+
+ // Use the lesser of the two step sizes
+ //if ( tmpStep < this.majorStep )
+ _majorStep = tmpStep;
+ }
+ else
+ _majorStep = (int) ( ( _max - _min - 1.0 ) / Default.MaxTextLabels ) + 1.0;
+
+ }
+ else
+ {
+ _majorStep = (int) _majorStep;
+ if ( _majorStep <= 0 )
+ _majorStep = 1.0;
+ }
+
+ if ( _minorStepAuto )
+ {
+ _minorStep = _majorStep / 10;
+
+ //_minorStep = CalcStepSize( _majorStep, 10 );
+ if ( _minorStep < 1 )
+ _minorStep = 1;
+ }
+
+ _mag = 0;
+ }
+
+ /// <summary>
+ /// Make a value label for an <see cref="AxisType.Text" /> <see cref="Axis" />.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="index">
+ /// The zero-based, ordinal index of the label to be generated. For example, a value of 2 would
+ /// cause the third value label on the axis to be generated.
+ /// </param>
+ /// <param name="dVal">
+ /// The numeric value associated with the label. This value is ignored for log (<see cref="Scale.IsLog"/>)
+ /// and text (<see cref="Scale.IsText"/>) type axes.
+ /// </param>
+ /// <returns>The resulting value label as a <see cref="string" /></returns>
+ override internal string MakeLabel( GraphPane pane, int index, double dVal )
+ {
+ if ( _format == null )
+ _format = Scale.Default.Format;
+
+ index *= (int) _majorStep;
+ if ( _textLabels == null || index < 0 || index >= _textLabels.Length )
+ return string.Empty;
+ else
+ return _textLabels[index];
+ }
+
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected TextScale( SerializationInfo info, StreamingContext context ) : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/Types.cs b/ZedGraph/Types.cs
new file mode 100644
index 0000000..fe28e7c
--- /dev/null
+++ b/ZedGraph/Types.cs
@@ -0,0 +1,868 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// Enumeration type for the various axis types that are available
+ /// </summary>
+ /// <seealso cref="ZedGraph.Axis.Type"/>
+ public enum AxisType
+ {
+ /// <summary> An ordinary, cartesian axis </summary>
+ Linear,
+ /// <summary> A base 10 log axis </summary>
+ Log,
+ /// <summary> A cartesian axis with calendar dates or times </summary>
+ Date,
+ /// <summary> An ordinal axis with user-defined text labels. An ordinal axis means that
+ /// all data points are evenly spaced at integral values, and the actual coordinate values
+ /// for points corresponding to that axis are ignored. That is, if the X axis is an
+ /// ordinal type, then all X values associated with the curves are ignored.</summary>
+ /// <seealso cref="AxisType.Ordinal"/>
+ /// <seealso cref="Scale.IsText"/>
+ /// <seealso cref="ZedGraph.Scale.Default.MaxTextLabels"/>
+ Text,
+ /// <summary> An ordinal axis with regular numeric labels. An ordinal axis means that
+ /// all data points are evenly spaced at integral values, and the actual coordinate values
+ /// for points corresponding to that axis are ignored. That is, if the X axis is an
+ /// ordinal type, then all X values associated with the curves are ignored. </summary>
+ /// <seealso cref="AxisType.Text"/>
+ /// <seealso cref="Scale.IsOrdinal"/>
+ Ordinal,
+ /// <summary> An ordinal axis that will have labels formatted with ordinal values corresponding
+ /// to the number of values in each <see cref="CurveItem" />.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="CurveItem" /> data points will be evenly-spaced at ordinal locations, and the
+ /// actual data values are ignored. </remarks>
+ /// <seealso cref="AxisType.Text"/>
+ /// <seealso cref="Scale.IsOrdinal"/>
+ DateAsOrdinal,
+ /// <summary> An ordinal axis that will have labels formatted with values from the actual data
+ /// values of the first <see cref="CurveItem" /> in the <see cref="CurveList" />.
+ /// </summary>
+ /// <remarks>
+ /// Although the tics are labeled with real data values, the actual points will be
+ /// evenly-spaced in spite of the data values. For example, if the X values of the first curve
+ /// are 1, 5, and 100, then the tic labels will show 1, 5, and 100, but they will be equal
+ /// distance from each other. </remarks>
+ /// <seealso cref="AxisType.Text"/>
+ /// <seealso cref="Scale.IsOrdinal"/>
+ LinearAsOrdinal,
+ /// <summary> An exponential axis </summary>
+ Exponent
+ }
+
+ /// <summary>
+ /// Enumeration type for the various types of fills that can be used with <see cref="Bar"/>
+ /// charts.
+ /// </summary>
+ public enum FillType
+ {
+ /// <summary> No fill </summary>
+ None,
+ /// <summary> A solid fill using <see cref="System.Drawing.SolidBrush"/> </summary>
+ Solid,
+ /// <summary> A custom fill using either <see cref="LinearGradientBrush"/> or
+ /// <see cref="TextureBrush"/></summary>
+ Brush,
+ /// <summary>
+ /// Fill with a single solid color based on the X value of the data.</summary>
+ /// <remarks>The X value is
+ /// used to determine the color value based on a gradient brush, and using a data range
+ /// of <see cref="Fill.RangeMin"/> and <see cref="Fill.RangeMax"/>. You can create a multicolor
+ /// range by initializing the <see cref="Fill"/> class with your own custom
+ /// <see cref="Brush"/> object based on a <see cref="ColorBlend"/>. In cases where a
+ /// data value makes no sense (<see cref="PaneBase.Fill"/>, <see cref="Legend.Fill"/>,
+ /// etc.), a default value of 50% of the range is assumed. The default range is 0 to 1.
+ /// </remarks>
+ /// <seealso cref="Fill.RangeMin"/>
+ /// <seealso cref="Fill.RangeMax"/>
+ /// <seealso cref="Fill.RangeDefault"/>
+ GradientByX,
+ /// <summary>
+ /// Fill with a single solid color based on the Z value of the data.</summary>
+ /// <remarks>The Z value is
+ /// used to determine the color value based on a gradient brush, and using a data range
+ /// of <see cref="Fill.RangeMin"/> and <see cref="Fill.RangeMax"/>. You can create a multicolor
+ /// range by initializing the <see cref="Fill"/> class with your own custom
+ /// <see cref="Brush"/> object based on a <see cref="ColorBlend"/>. In cases where a
+ /// data value makes no sense (<see cref="PaneBase.Fill"/>, <see cref="Legend.Fill"/>,
+ /// etc.), a default value of 50% of the range is assumed. The default range is 0 to 1.
+ /// </remarks>
+ /// <seealso cref="Fill.RangeMin"/>
+ /// <seealso cref="Fill.RangeMax"/>
+ /// <seealso cref="Fill.RangeDefault"/>
+ GradientByY,
+ /// <summary>
+ /// Fill with a single solid color based on the Z value of the data.</summary>
+ /// <remarks>The Z value is
+ /// used to determine the color value based on a gradient brush, and using a data range
+ /// of <see cref="Fill.RangeMin"/> and <see cref="Fill.RangeMax"/>. You can create a multicolor
+ /// range by initializing the <see cref="Fill"/> class with your own custom
+ /// <see cref="Brush"/> object based on a <see cref="ColorBlend"/>. In cases where a
+ /// data value makes no sense (<see cref="PaneBase.Fill"/>, <see cref="Legend.Fill"/>,
+ /// etc.), a default value of 50% of the range is assumed. The default range is 0 to 1.
+ /// </remarks>
+ /// <seealso cref="Fill.RangeMin"/>
+ /// <seealso cref="Fill.RangeMax"/>
+ /// <seealso cref="Fill.RangeDefault"/>
+ GradientByZ,
+ /// <summary>
+ /// Fill with a single solid color based on the "ColorValue" property of the data.</summary>
+ /// <remarks>The "ColorValue" property is
+ /// used to determine the color value based on a gradient brush, and using a data range
+ /// of <see cref="Fill.RangeMin"/> and <see cref="Fill.RangeMax"/>. You can create a multicolor
+ /// range by initializing the <see cref="Fill"/> class with your own custom
+ /// <see cref="Brush"/> object based on a <see cref="ColorBlend"/>. In cases where a
+ /// data value makes no sense (<see cref="PaneBase.Fill"/>, <see cref="Legend.Fill"/>,
+ /// etc.), a default value of 50% of the range is assumed. The default range is 0 to 1.
+ /// </remarks>
+ /// <seealso cref="Fill.RangeMin"/>
+ /// <seealso cref="Fill.RangeMax"/>
+ /// <seealso cref="Fill.RangeDefault"/>
+ GradientByColorValue
+
+ }
+
+ /// <summary>
+ /// Enumeration type for the various axis date and time unit types that are available
+ /// </summary>
+ public enum DateUnit
+ {
+ /// <summary> Yearly units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Year,
+ /// <summary> Monthly units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Month,
+ /// <summary> Daily units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Day,
+ /// <summary> Hourly units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Hour,
+ /// <summary> Minute units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Minute,
+ /// <summary> Second units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Second,
+ /// <summary> Millisecond units <see cref="Scale.MajorUnit"/> and <see cref="Scale.MinorUnit"/>
+ /// </summary>
+ Millisecond
+ }
+
+ /// <summary>
+ /// Enumeration type for the various symbol shapes that are available
+ /// </summary>
+ /// <seealso cref="ZedGraph.Symbol.Fill"/>
+ public enum SymbolType
+ {
+ /// <summary> Square-shaped <see cref="ZedGraph.Symbol"/> </summary>
+ Square,
+ /// <summary> Rhombus-shaped <see cref="ZedGraph.Symbol"/> </summary>
+ Diamond,
+ /// <summary> Equilateral triangle <see cref="ZedGraph.Symbol"/> </summary>
+ Triangle,
+ /// <summary> Uniform circle <see cref="ZedGraph.Symbol"/> </summary>
+ Circle,
+ /// <summary> "X" shaped <see cref="ZedGraph.Symbol"/>. This symbol cannot
+ /// be filled since it has no outline. </summary>
+ XCross,
+ /// <summary> "+" shaped <see cref="ZedGraph.Symbol"/>. This symbol cannot
+ /// be filled since it has no outline. </summary>
+ Plus,
+ /// <summary> Asterisk-shaped <see cref="ZedGraph.Symbol"/>. This symbol
+ /// cannot be filled since it has no outline. </summary>
+ Star,
+ /// <summary> Unilateral triangle <see cref="ZedGraph.Symbol"/>, pointing
+ /// down. </summary>
+ TriangleDown,
+ /// <summary>
+ /// Horizontal dash <see cref="ZedGraph.Symbol"/>. This symbol cannot be
+ /// filled since it has no outline.
+ /// </summary>
+ HDash,
+ /// <summary>
+ /// Vertical dash <see cref="ZedGraph.Symbol"/>. This symbol cannot be
+ /// filled since it has no outline.
+ /// </summary>
+ VDash,
+ /// <summary> A symbol defined by the <see cref="Symbol.UserSymbol"/> propery.
+ /// If no symbol is defined, the <see cref="Symbol.Default.Type"/>. symbol will
+ /// be used.
+ /// </summary>
+ UserDefined,
+ /// <summary> A Default symbol type (the symbol type will be obtained
+ /// from <see cref="Symbol.Default.Type"/>. </summary>
+ Default,
+ /// <summary> No symbol is shown (this is equivalent to using
+ /// <see cref="Symbol.IsVisible"/> = false.</summary>
+ None
+ }
+
+ /// <summary>
+ /// Enumeration type that defines the possible legend locations
+ /// </summary>
+ /// <seealso cref="Legend.Position"/>
+ public enum LegendPos
+ {
+ /// <summary>
+ /// Locate the <see cref="Legend"/> above the <see cref="Chart.Rect"/>
+ /// </summary>
+ Top,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> on the left side of the <see cref="Chart.Rect"/>
+ /// </summary>
+ Left,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> on the right side of the <see cref="Chart.Rect"/>
+ /// </summary>
+ Right,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> below the <see cref="Chart.Rect"/>
+ /// </summary>
+ Bottom,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> inside the <see cref="Chart.Rect"/> in the
+ /// top-left corner.
+ /// </summary>
+ InsideTopLeft,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> inside the <see cref="Chart.Rect"/> in the
+ /// top-right corner.
+ /// </summary>
+ InsideTopRight,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> inside the <see cref="Chart.Rect"/> in the
+ /// bottom-left corner.
+ /// </summary>
+ InsideBotLeft,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> inside the <see cref="Chart.Rect"/> in the
+ /// bottom-right corner.
+ /// </summary>
+ InsideBotRight,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> as a floating object above the graph at the
+ /// location specified by <see cref="Legend.Location"/>.
+ /// </summary>
+ Float,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> centered above the <see cref="Chart.Rect"/>
+ /// </summary>
+ TopCenter,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> centered below the <see cref="Chart.Rect"/>
+ /// </summary>
+ BottomCenter,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> above the <see cref="Chart.Rect"/>, but flush
+ /// against the left margin of the <see cref="PaneBase.Rect" />.
+ /// </summary>
+ TopFlushLeft,
+ /// <summary>
+ /// Locate the <see cref="Legend"/> below the <see cref="Chart.Rect"/>, but flush
+ /// against the left margin of the <see cref="PaneBase.Rect" />.
+ /// </summary>
+ BottomFlushLeft
+
+ }
+
+ /// <summary>
+ /// Enumeration type for the different horizontal text alignment options
+ /// </summary>
+ /// <seealso cref="FontSpec"/>
+ public enum AlignH
+ {
+ /// <summary>
+ /// Position the text so that its left edge is aligned with the
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ Left,
+ /// <summary>
+ /// Position the text so that its center is aligned (horizontally) with the
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ Center,
+ /// <summary>
+ /// Position the text so that its right edge is aligned with the
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ Right
+ }
+
+ /// <summary>
+ /// Enumeration type for the different proximal alignment options
+ /// </summary>
+ /// <seealso cref="FontSpec"/>
+ /// <seealso cref="Scale.Align"/>
+ public enum AlignP
+ {
+ /// <summary>
+ /// Position the text so that its "inside" edge (the edge that is
+ /// nearest to the alignment reference point or object) is aligned.
+ /// Used by the <see cref="Scale.Align"/> method to align text
+ /// to the axis.
+ /// </summary>
+ Inside,
+ /// <summary>
+ /// Position the text so that its center is aligned with the
+ /// reference object or point.
+ /// Used by the <see cref="Scale.Align"/> method to align text
+ /// to the axis.
+ /// </summary>
+ Center,
+ /// <summary>
+ /// Position the text so that its right edge (the edge that is
+ /// farthest from the alignment reference point or object) is aligned.
+ /// Used by the <see cref="Scale.Align"/> method to align text
+ /// to the axis.
+ /// </summary>
+ Outside
+ }
+
+ /// <summary>
+ /// Enumeration type for the different vertical text alignment options
+ /// </summary>
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ public enum AlignV
+ {
+ /// <summary>
+ /// Position the text so that its top edge is aligned with the
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ Top,
+ /// <summary>
+ /// Position the text so that its center is aligned (vertically) with the
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ Center,
+ /// <summary>
+ /// Position the text so that its bottom edge is aligned with the
+ /// specified X,Y location. Used by the
+ /// <see cref="FontSpec.Draw(Graphics,PaneBase,string,float,float,AlignH,AlignV,float)"/> method.
+ /// </summary>
+ Bottom
+ }
+
+ /// <summary>
+ /// Enumeration type for the user-defined coordinate types available.
+ /// These coordinate types are used the <see cref="ArrowObj"/> objects
+ /// and <see cref="TextObj"/> objects only.
+ /// </summary>
+ /// <seealso cref="ZedGraph.Location.CoordinateFrame"/>
+ public enum CoordType
+ {
+ /// <summary>
+ /// Coordinates are specified as a fraction of the
+ /// <see cref="Chart.Rect"/>. That is, for the X coordinate, 0.0
+ /// is at the left edge of the ChartRect and 1.0
+ /// is at the right edge of the ChartRect. A value less
+ /// than zero is left of the ChartRect and a value
+ /// greater than 1.0 is right of the ChartRect. For the Y coordinate, 0.0
+ /// is the top and 1.0 is the bottom.
+ /// </summary>
+ ChartFraction,
+ /// <summary>
+ /// Coordinates are specified as a fraction of the
+ /// <see cref="PaneBase.Rect"/>. That is, for the X coordinate, 0.0
+ /// is at the left edge of the Rect and 1.0
+ /// is at the right edge of the Rect. A value less
+ /// than zero is left of the Rect and a value
+ /// greater than 1.0 is right of the Rect. For the Y coordinate, 0.0
+ /// is the top and 1.0 is the bottom. Note that
+ /// any value less than zero or greater than 1.0 will be outside
+ /// the Rect, and therefore clipped.
+ /// </summary>
+ PaneFraction,
+ /// <summary>
+ /// Coordinates are specified according to the user axis scales
+ /// for the <see cref="GraphPane.XAxis"/> and <see cref="GraphPane.YAxis"/>.
+ /// </summary>
+ AxisXYScale,
+ /// <summary>
+ /// Coordinates are specified according to the user axis scales
+ /// for the <see cref="GraphPane.XAxis"/> and <see cref="GraphPane.Y2Axis"/>.
+ /// </summary>
+ AxisXY2Scale,
+ /// <summary>
+ /// The X coordinate is specified as a fraction of the <see cref="Chart.Rect"/>,
+ /// and the Y coordinate is specified as a fraction of the <see cref="PaneBase.Rect" />.
+ /// </summary>
+ /// <remarks>
+ /// For the X coordinate, 0.0
+ /// is at the left edge of the ChartRect and 1.0
+ /// is at the right edge of the ChartRect. A value less
+ /// than zero is left of the ChartRect and a value
+ /// greater than 1.0 is right of the ChartRect. For the Y coordinate, a value of zero is at
+ /// the left side of the pane, and a value of 1.0 is at the right side of the pane.
+ /// </remarks>
+ XChartFractionYPaneFraction,
+ /// <summary>
+ /// The X coordinate is specified as a fraction of the <see cref="PaneBase.Rect"/>,
+ /// and the Y coordinate is specified as a fraction of the <see cref="Chart.Rect" />.
+ /// </summary>
+ /// <remarks>
+ /// For the X coordinate, a value of zero is at
+ /// the left side of the pane, and a value of 1.0 is at the right side of the pane.
+ /// For the Y coordinate, 0.0
+ /// is at the top edge of the ChartRect and 1.0
+ /// is at the bottom edge of the ChartRect. A value less
+ /// than zero is above the ChartRect and a value
+ /// greater than 1.0 is below the ChartRect.
+ /// </remarks>
+ XPaneFractionYChartFraction,
+ /// <summary>
+ /// The X coordinate is specified as an X Scale value, and the Y coordinate
+ /// is specified as a fraction of the <see cref="Chart.Rect"/>.
+ /// </summary>
+ /// <remarks>
+ /// For the X coordinate, the value just corresponds to the values of the X scale.
+ /// Values outside the scale range will be
+ /// outside the <see cref="Chart.Rect" />. For the Y coordinate, 0.0
+ /// is at the top edge of the ChartRect and 1.0
+ /// is at the bottom edge of the ChartRect. A value less
+ /// than zero is above the ChartRect and a value
+ /// greater than 1.0 is below the ChartRect.
+ /// </remarks>
+ XScaleYChartFraction,
+ /// <summary>
+ /// The X coordinate is specified as a fraction of the
+ /// <see cref="Chart.Rect"/> and the Y coordinate is specified as
+ /// a Y scale value.
+ /// </summary>
+ /// <remarks>
+ /// For the X coordinate, 0.0
+ /// is at the left edge of the ChartRect and 1.0
+ /// is at the right edge of the ChartRect. A value less
+ /// than zero is left of the ChartRect and a value
+ /// greater than 1.0 is right of the ChartRect. For the Y coordinate, the value just
+ /// corresponds to the values of the Y scale. Values outside the scale range will be
+ /// outside the <see cref="Chart.Rect" />.
+ /// </remarks>
+ XChartFractionYScale,
+ /// <summary>
+ /// The X coordinate is specified as a fraction of the
+ /// <see cref="Chart.Rect"/> and the Y coordinate is specified as
+ /// a Y2 scale value.
+ /// </summary>
+ /// <remarks>
+ /// For the X coordinate, 0.0
+ /// is at the left edge of the ChartRect and 1.0
+ /// is at the right edge of the ChartRect. A value less
+ /// than zero is left of the ChartRect and a value
+ /// greater than 1.0 is right of the ChartRect. For the Y coordinate, the value just
+ /// corresponds to the values of the Y2 scale. Values outside the scale range will be
+ /// outside the <see cref="Chart.Rect" />.
+ /// </remarks>
+ XChartFractionY2Scale
+
+ }
+
+ /// <summary>
+ /// Enumeration type that defines how a curve is drawn. Curves can be drawn
+ /// as ordinary lines by connecting the points directly, or in a stair-step
+ /// fashion as a series of discrete, constant values. In a stair step plot,
+ /// all lines segments are either horizontal or vertical. In a non-step (line)
+ /// plot, the lines can be any angle.
+ /// </summary>
+ /// <seealso cref="Line.StepType"/>
+ public enum StepType
+ {
+ /// <summary>
+ /// Draw the <see cref="CurveItem"/> as a stair-step in which each
+ /// point defines the
+ /// beginning (left side) of a new stair. This implies the points are
+ /// defined at the beginning of an "event."
+ /// </summary>
+ ForwardStep,
+ /// <summary>
+ /// Draw the <see cref="CurveItem"/> as a stair-step in which each
+ /// point defines the end (right side) of a new stair. This implies
+ /// the points are defined at the end of an "event."
+ /// </summary>
+ RearwardStep,
+ /// <summary>
+ /// Draw the <see cref="CurveItem"/> as an ordinary line, in which the
+ /// points are connected directly by line segments.
+ /// </summary>
+ NonStep,
+ /// <summary>
+ /// Draw the <see cref="CurveItem"/> as a segment in which each point defines the
+ /// beginning (left side) of a new "stair." This implies the points are defined
+ /// at the beginning of an "event." Note that ForwardSegment is different
+ /// from ForwardStep in that it does not draw the vertical portion of the step.
+ /// </summary>
+ ForwardSegment,
+ /// <summary>
+ /// Draw the <see cref="CurveItem"/> as a segment in which each point defines the
+ /// end (right side) of a new "stair." This implies the points are defined
+ /// at the end of an "event." Note that RearwardSegment is different
+ /// from RearwardStep in that it does not draw the vertical portion of the step.
+ /// </summary>
+ RearwardSegment
+ }
+
+ /// <summary>
+ /// Enumeration type that defines the base axis from which <see cref="Bar"/> graphs
+ /// are displayed. The bars can be drawn on any of the four axes (<see cref="XAxis"/>,
+ /// <see cref="X2Axis"/>, <see cref="YAxis"/>, and <see cref="Y2Axis"/>).
+ /// </summary>
+ /// <seealso cref="BarSettings.Base"/>
+ public enum BarBase
+ {
+ /// <summary>
+ /// Draw the <see cref="Bar"/> chart based from the <see cref="XAxis"/>.
+ /// </summary>
+ X,
+ /// <summary>
+ /// Draw the <see cref="Bar"/> chart based from the <see cref="X2Axis"/>.
+ /// </summary>
+ X2,
+ /// <summary>
+ /// Draw the <see cref="Bar"/> chart based from the <see cref="YAxis"/>.
+ /// </summary>
+ Y,
+ /// <summary>
+ /// Draw the <see cref="Bar"/> chart based from the <see cref="Y2Axis"/>.
+ /// </summary>
+ Y2
+ }
+
+ /// <summary>
+ /// Enumeration type that defines the available types of <see cref="LineItem"/> graphs.
+ /// </summary>
+ /// <seealso cref="GraphPane.LineType"/>
+ public enum LineType
+ {
+ /// <summary>
+ /// Draw the lines as normal. Any fill area goes from each line down to the X Axis.
+ /// </summary>
+ Normal,
+ /// <summary>
+ /// Draw the lines stacked on top of each other, accumulating values to a total value.
+ /// </summary>
+ Stack
+ }
+
+ /// <summary>
+ /// Enumeration type that defines the available types of <see cref="BarItem"/> graphs.
+ /// </summary>
+ /// <seealso cref="BarSettings.Type"/>
+ public enum BarType
+ {
+ /// <summary>
+ /// Draw each <see cref="BarItem"/> side by side in clusters.
+ /// </summary>
+ Cluster,
+ /// <summary>
+ /// Draw the <see cref="BarItem"/> bars one on top of the other. The bars will
+ /// be drawn such that the last bar in the <see cref="CurveList"/> will be behind
+ /// all other bars. Note that the bar values are not summed up for the overlay
+ /// mode. The data values must be summed before being passed
+ /// to <see cref="GraphPane.AddBar(string,IPointList,Color)"/>.
+ /// For example, if the first bar of
+ /// the first <see cref="BarItem"/> has a value of 100, and the first bar of
+ /// the second <see cref="BarItem"/> has a value of 120, then that bar will
+ /// appear to be 20 units on top of the first bar.
+ /// </summary>
+ Overlay,
+ /// <summary>
+ /// Draw the <see cref="BarItem"/> bars one on top of the other. The bars will
+ /// be drawn such that the bars are sorted according to the maximum value, with
+ /// the tallest bar at each point at the back and the shortest bar at the front.
+ /// This is similar to the <see cref="Overlay"/> mode, but the bars are sorted at
+ /// each base value.
+ /// The data values must be summed before being passed
+ /// to <see cref="GraphPane.AddBar(string,IPointList,Color)"/>. For example, if the first bar of
+ /// the first <see cref="BarItem"/> has a value of 100, and the first bar of
+ /// the second <see cref="BarItem"/> has a value of 120, then that bar will
+ /// appear to be 20 units on top of the first bar.
+ /// </summary>
+ SortedOverlay,
+ /// <summary>
+ /// Draw the <see cref="BarItem"/> bars in an additive format so that they stack on
+ /// top of one another. The value of the last bar drawn will be the sum of the values
+ /// of all prior bars.
+ /// </summary>
+ Stack,
+ /// <summary>
+ /// Draw the <see cref="BarItem"/> bars in a format whereby the height of each
+ /// represents the percentage of the total each one represents. Negative values
+ ///are displayed below the zero line as percentages of the absolute total of all values.
+ /// </summary>
+ PercentStack
+ }
+
+ /// <summary>
+ /// Enumeration type that defines which set of data points - X or Y - is used
+ /// <seealso cref="System.Collections.ArrayList.Sort()"/> to perform the sort.
+ /// </summary>
+ public enum SortType
+ {
+ /// <summary>
+ /// Use the Y values to sort the list.
+ /// </summary>
+ YValues,
+ /// <summary>
+ /// Use the X values to sort the list.
+ /// </summary>
+ XValues
+ };
+
+ /// <summary>
+ /// Enumeration that specifies a Z-Order position for <see cref="GraphObj"/>
+ /// objects.
+ /// </summary>
+ /// <remarks>This enumeration allows you to set the layering of various graph
+ /// features. Except for the <see cref="GraphObj"/> objects, other feature types
+ /// all have a fixed depth as follows (front to back):
+ /// <list>
+ /// <see cref="Legend"/> objects
+ /// The border around <see cref="Chart.Rect"/>
+ /// <see cref="CurveItem"/> objects
+ /// The <see cref="Axis"/> features
+ /// The background fill of the <see cref="Chart.Rect"/>
+ /// The pane <see cref="PaneBase.Title"/>
+ /// The background fill of the <see cref="PaneBase.Rect"/>
+ /// </list>
+ /// You cannot place anything behind the <see cref="PaneBase.Rect"/>
+ /// background fill, but <see cref="GraphObj.ZOrder"/> allows you to
+ /// explicitly control the depth of <see cref="GraphObj"/> objects
+ /// between all other object types. For items of equal <see cref="ZOrder"/>,
+ /// such as multiple <see cref="CurveItem"/>'s or <see cref="GraphObj"/>'s
+ /// having the same <see cref="ZOrder"/> value, the relative depth is
+ /// controlled by the ordinal position in the list (either
+ /// <see cref="CurveList"/> or <see cref="GraphObjList"/>).
+ /// <see cref="GraphObj"/> objects
+ /// can be placed in the <see cref="GraphObjList"/> of either a
+ /// <see cref="GraphPane"/> or a <see cref="MasterPane"/>. For a
+ /// <see cref="GraphPane"/>-based <see cref="GraphObj"/>, all <see cref="ZOrder"/>
+ /// values are applicable. For a <see cref="MasterPane"/>-based
+ /// <see cref="GraphObj"/>, any <see cref="ZOrder"/> value can be used, but there
+ /// are really only three depths:
+ /// <list><see cref="ZOrder.H_BehindAll"/> will place the item behind the pane title,
+ /// <see cref="ZOrder.A_InFront"/> will place on top of all other graph features,
+ /// any other value places the object above the pane title, but behind the <see cref="GraphPane"/>'s.
+ /// </list>
+ /// </remarks>
+ public enum ZOrder
+ {
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind all other
+ /// objects (including the <see cref="PaneBase"/> <see cref="PaneBase.Title"/>).
+ /// </summary>
+ H_BehindAll,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind the
+ /// <see cref="Chart.Rect"/> background <see cref="Fill"/>
+ /// (see <see cref="Chart.Fill"/>).
+ /// </summary>
+ G_BehindChartFill,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind the grid lines.
+ /// </summary>
+ F_BehindGrid,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind the
+ /// <see cref="CurveItem"/> objects.
+ /// </summary>
+ E_BehindCurves,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind the
+ /// <see cref="Axis"/> objects.
+ /// </summary>
+ D_BehindAxis,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind the
+ /// <see cref="Chart"/> border.
+ /// </summary>
+ C_BehindChartBorder,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be behind the
+ /// <see cref="Legend"/> object.
+ /// </summary>
+ B_BehindLegend,
+ /// <summary>
+ /// Specifies that the <see cref="GraphObj"/> will be in front of
+ /// all other objects, except for the other <see cref="GraphObj"/>
+ /// objects that have the same <see cref="ZOrder"/> and are before
+ /// this object in the <see cref="GraphObjList"/>.
+ /// </summary>
+ A_InFront
+ }
+
+ /// <summary>
+ /// Enumeration that determines the type of label that is displayed for each pie slice
+ /// (see <see cref="PieItem.LabelType"/>).
+ /// </summary>
+ public enum PieLabelType
+ {
+ /// <summary>
+ /// Displays <see cref="CurveItem.Label"/> and <see cref="PieItem.Value"/> for
+ /// a slice in a Pie Chart.
+ /// </summary>
+ Name_Value,
+
+ /// <summary>
+ /// Displays <see cref="CurveItem.Label"/> and <see cref="PieItem.Value"/> (as % of total) for
+ /// a slice in a Pie Chart.
+ /// </summary>
+ Name_Percent,
+
+ /// <summary>
+ /// Displays a <see cref="CurveItem.Label"/> containing the <see cref="PieItem.Value"/> both
+ /// as an absolute number and as percentage of the total.
+ /// </summary>
+ Name_Value_Percent,
+
+ /// <summary>
+ /// Displays <see cref="PieItem.Value"/> for
+ /// a slice in a Pie Chart.
+ /// </summary>
+ Value,
+
+ /// <summary>
+ /// Displays <see cref="PieItem.Value"/> (as % of total) for
+ /// a slice in a Pie Chart.
+ /// </summary>
+ Percent,
+
+ /// <summary>
+ /// Displays <see cref="CurveItem.Label"/> for a slice in a Pie Chart.
+ /// </summary>
+ Name,
+
+ /// <summary>
+ ///No label displayed.
+ /// </summary>
+ None
+ }
+
+ /// <summary>
+ /// Define the auto layout options for the
+ /// <see cref="MasterPane.SetLayout(Graphics,PaneLayout)"/> method.
+ /// </summary>
+ public enum PaneLayout
+ {
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s so they are in a square grid (always 2x2, 3x3, 4x4),
+ /// leaving blank spaces as required.
+ /// </summary>
+ /// <remarks>For example, a single pane would generate a 1x1 grid, between 2 and 4 panes would generate
+ /// a 2x2 grid, 5 to 9 panes would generate a 3x3 grid.</remarks>
+ ForceSquare,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s so they are in a general square (2x2, 3x3, etc.), but use extra
+ /// columns when necessary (row x column = 1x2, 2x3, 3x4, etc.) depending on the total number
+ /// of panes required.
+ /// </summary>
+ /// <remarks>For example, a 2x2 grid has four panes and a 3x3 grid has 9 panes. If there are
+ /// 6 panes required, then this option will eliminate a row (column preferred) to make a
+ /// 2 row x 3 column grid. With 7 panes, it will make a 3x3 grid with 2 empty spaces.</remarks>
+ SquareColPreferred,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s so they are in a general square (2x2, 3x3, etc.), but use extra
+ /// rows when necessary (2x1, 3x2, 4x3, etc.) depending on the total number of panes required.
+ /// </summary>
+ /// <remarks>For example, a 2x2 grid has four panes and a 3x3 grid has 9 panes. If there are
+ /// 6 panes required, then this option will eliminate a column (row preferred) to make a
+ /// 3 row x 2 column grid. With 7 panes, it will make a 3x3 grid with 2 empty spaces.</remarks>
+ SquareRowPreferred,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s in a single row
+ /// </summary>
+ SingleRow,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s in a single column
+ /// </summary>
+ SingleColumn,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of columns: The first row has
+ /// 1 column and the second row has 2 columns for a total of 3 panes.
+ /// </summary>
+ ExplicitCol12,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of columns: The first row has
+ /// 2 columns and the second row has 1 column for a total of 3 panes.
+ /// </summary>
+ ExplicitCol21,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of columns: The first row has
+ /// 2 columns and the second row has 3 columns for a total of 5 panes.
+ /// </summary>
+ ExplicitCol23,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of columns: The first row has
+ /// 3 columns and the second row has 2 columns for a total of 5 panes.
+ /// </summary>
+ ExplicitCol32,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of rows: The first column has
+ /// 1 row and the second column has 2 rows for a total of 3 panes.
+ /// </summary>
+ ExplicitRow12,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of rows: The first column has
+ /// 2 rows and the second column has 1 row for a total of 3 panes.
+ /// </summary>
+ ExplicitRow21,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of rows: The first column has
+ /// 2 rows and the second column has 3 rows for a total of 5 panes.
+ /// </summary>
+ ExplicitRow23,
+ /// <summary>
+ /// Layout the <see cref="GraphPane"/>'s with an explicit number of rows: The first column has
+ /// 3 rows and the second column has 2 rows for a total of 5 panes.
+ /// </summary>
+ ExplicitRow32
+ }
+
+ /// <summary>
+ /// Enum for specifying the type of data to be returned by the ZedGraphWeb Render() method.
+ /// </summary>
+ public enum RenderModeType
+ {
+ /// <summary>
+ /// Renders as an IMG tag referencing a local generated image. ContentType stays text.
+ /// </summary>
+ ImageTag,
+ /// <summary>
+ /// Renders the binary image. ContentType is changed accordingly.
+ /// </summary>
+ RawImage
+ }
+
+
+}
\ No newline at end of file
diff --git a/ZedGraph/ValueHandler.cs b/ZedGraph/ValueHandler.cs
new file mode 100644
index 0000000..facd696
--- /dev/null
+++ b/ZedGraph/ValueHandler.cs
@@ -0,0 +1,372 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+using System;
+using System.Text;
+using System.Drawing;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class designed to simplify the process of getting the actual value for
+ /// the various stacked and regular curve types
+ /// </summary>
+ ///
+ /// <author> John Champion</author>
+ /// <version> $Revision: 3.21 $ $Date: 2008-12-02 12:55:34 $ </version>
+ public class ValueHandler
+ {
+ private GraphPane _pane;
+
+ /// <summary>
+ /// Basic constructor that saves a reference to the parent
+ /// <see cref="GraphPane"/> object.
+ /// </summary>
+ /// <param name="pane">The parent <see cref="GraphPane"/> object.</param>
+ /// <param name="initialize">A <see cref="bool"/> flag to indicate whether or
+ /// not the drawing variables should be initialized. Initialization is not
+ /// required if this is part of a ZedGraph internal draw operation (i.e., its in
+ /// the middle of a call to <see cref="GraphPane.Draw"/>). Otherwise, you should
+ /// initialize to make sure the drawing variables are configured. true to do
+ /// an initialization, false otherwise.</param>
+ public ValueHandler( GraphPane pane, bool initialize )
+ {
+ _pane = pane;
+ if ( initialize )
+ {
+ // just create a dummy image, which results in a full draw operation
+ using ( Image image = pane.GetImage() )
+ {
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get the user scale values associate with a particular point of a
+ /// particular curve.</summary>
+ /// <remarks>The main purpose of this method is to handle
+ /// stacked bars, in which case the stacked values are returned rather
+ /// than the individual data values.
+ /// </remarks>
+ /// <param name="curve">A <see cref="CurveItem"/> object of interest.</param>
+ /// <param name="iPt">The zero-based point index for the point of interest.</param>
+ /// <param name="baseVal">A <see cref="Double"/> value representing the value
+ /// for the independent axis.</param>
+ /// <param name="lowVal">A <see cref="Double"/> value representing the lower
+ /// value for the dependent axis.</param>
+ /// <param name="hiVal">A <see cref="Double"/> value representing the upper
+ /// value for the dependent axis.</param>
+ /// <returns>true if the data point is value, false for
+ /// <see cref="PointPairBase.Missing"/>, invalid, etc. data.</returns>
+ public bool GetValues( CurveItem curve, int iPt, out double baseVal,
+ out double lowVal, out double hiVal )
+ {
+ return GetValues( _pane, curve, iPt, out baseVal,
+ out lowVal, out hiVal );
+ }
+
+ /// <summary>
+ /// Get the user scale values associate with a particular point of a
+ /// particular curve.</summary>
+ /// <remarks>The main purpose of this method is to handle
+ /// stacked bars and lines, in which case the stacked values are returned rather
+ /// than the individual data values. However, this method works generically for any
+ /// curve type.
+ /// </remarks>
+ /// <param name="pane">The parent <see cref="GraphPane"/> object.</param>
+ /// <param name="curve">A <see cref="CurveItem"/> object of interest.</param>
+ /// <param name="iPt">The zero-based point index for the point of interest.</param>
+ /// <param name="baseVal">A <see cref="Double"/> value representing the value
+ /// for the independent axis.</param>
+ /// <param name="lowVal">A <see cref="Double"/> value representing the lower
+ /// value for the dependent axis.</param>
+ /// <param name="hiVal">A <see cref="Double"/> value representing the upper
+ /// value for the dependent axis.</param>
+ /// <returns>true if the data point is value, false for
+ /// <see cref="PointPairBase.Missing"/>, invalid, etc. data.</returns>
+ public static bool GetValues( GraphPane pane, CurveItem curve, int iPt,
+ out double baseVal, out double lowVal, out double hiVal )
+ {
+ hiVal = PointPair.Missing;
+ lowVal = PointPair.Missing;
+ baseVal = PointPair.Missing;
+
+ if ( curve == null || curve.Points.Count <= iPt || !curve.IsVisible )
+ return false;
+
+ Axis baseAxis = curve.BaseAxis( pane );
+ Axis valueAxis = curve.ValueAxis( pane );
+
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ baseVal = curve.Points[iPt].X;
+ else
+ baseVal = curve.Points[iPt].Y;
+
+ // is it a stacked bar type?
+ if ( curve is BarItem && ( pane._barSettings.Type == BarType.Stack ||
+ pane._barSettings.Type == BarType.PercentStack ) )
+ {
+ double positiveStack = 0;
+ double negativeStack = 0;
+ double curVal;
+
+ // loop through all the curves, summing up the values to get a total (only
+ // for the current ordinal position iPt)
+ foreach ( CurveItem tmpCurve in pane.CurveList )
+ {
+ // Sum the value for the current curve only if it is a bar
+ if ( tmpCurve.IsBar && tmpCurve.IsVisible )
+ {
+ curVal = PointPair.Missing;
+ // For non-ordinal curves, find a matching base value (must match exactly)
+ if ( curve.IsOverrideOrdinal || !baseAxis._scale.IsAnyOrdinal )
+ {
+ IPointList points = tmpCurve.Points;
+
+ for ( int i=0; i<points.Count; i++ )
+ {
+ if ( ( baseAxis is XAxis || baseAxis is X2Axis ) && points[i].X == baseVal )
+ {
+ curVal = points[i].Y;
+ break;
+ }
+ else if ( !(baseAxis is XAxis || baseAxis is X2Axis) && points[i].Y == baseVal )
+ {
+ curVal = points[i].X;
+ break;
+ }
+ }
+ }
+ // otherwise, it's an ordinal type so use the value at the same ordinal position
+ else if ( iPt < tmpCurve.Points.Count )
+ {
+ // Get the value for the appropriate value axis
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ curVal = tmpCurve.Points[iPt].Y;
+ else
+ curVal = tmpCurve.Points[iPt].X;
+ }
+
+ // If it's a missing value, skip it
+ if ( curVal == PointPair.Missing )
+ {
+ positiveStack = PointPair.Missing;
+ negativeStack = PointPair.Missing;
+ }
+
+ // the current curve is the target curve, save the summed values for later
+ if ( tmpCurve == curve )
+ {
+ // if the value is positive, use the positive stack
+ if ( curVal >= 0 )
+ {
+ lowVal = positiveStack;
+ hiVal = ( curVal == PointPair.Missing || positiveStack == PointPair.Missing ) ?
+ PointPair.Missing : positiveStack + curVal;
+ }
+ // otherwise, use the negative stack
+ else
+ {
+ hiVal = negativeStack;
+ lowVal = ( curVal == PointPair.Missing || negativeStack == PointPair.Missing ) ?
+ PointPair.Missing : negativeStack + curVal;
+ }
+ }
+
+ // Add all positive values to the positive stack, and negative values to the
+ // negative stack
+ if ( curVal >= 0 )
+ positiveStack = ( curVal == PointPair.Missing || positiveStack == PointPair.Missing ) ?
+ PointPair.Missing : positiveStack + curVal;
+ else
+ negativeStack = ( curVal == PointPair.Missing || negativeStack == PointPair.Missing ) ?
+ PointPair.Missing : negativeStack + curVal;
+ }
+ }
+
+ // if the curve is a PercentStack type, then calculate the percent for this bar
+ // based on the total height of the stack
+ if ( pane._barSettings.Type == BarType.PercentStack &&
+ hiVal != PointPair.Missing && lowVal != PointPair.Missing )
+ {
+ // Use the total magnitude of the positive plus negative bar stacks to determine
+ // the percentage value
+ positiveStack += Math.Abs( negativeStack );
+
+ // just to avoid dividing by zero...
+ if ( positiveStack != 0 )
+ {
+ // calculate the percentage values
+ lowVal = lowVal / positiveStack * 100.0;
+ hiVal = hiVal / positiveStack * 100.0;
+ }
+ else
+ {
+ lowVal = 0;
+ hiVal = 0;
+ }
+ }
+
+ if ( baseVal == PointPair.Missing || lowVal == PointPair.Missing ||
+ hiVal == PointPair.Missing )
+ return false;
+ else
+ return true;
+ }
+ // If the curve is a stacked line type, then sum up the values similar to the stacked bar type
+ else if ( curve is LineItem && pane.LineType == LineType.Stack )
+ {
+ double stack = 0;
+ double curVal;
+
+ // loop through all the curves, summing up the values to get a total (only
+ // for the current ordinal position iPt)
+ foreach ( CurveItem tmpCurve in pane.CurveList )
+ {
+ // make sure the curve is a Line type
+ if ( tmpCurve is LineItem && tmpCurve.IsVisible )
+ {
+ curVal = PointPair.Missing;
+ // For non-ordinal curves, find a matching base value (must match exactly)
+ if ( curve.IsOverrideOrdinal || !baseAxis._scale.IsAnyOrdinal )
+ {
+ IPointList points = tmpCurve.Points;
+
+ for ( int i = 0; i < points.Count; i++ )
+ {
+ if ( points[i].X == baseVal )
+ {
+ curVal = points[i].Y;
+ break;
+ }
+ }
+ }
+ // otherwise, it's an ordinal type so use the value at the same ordinal position
+ else if ( iPt < tmpCurve.Points.Count )
+ {
+ // For line types, the Y axis is always the value axis
+ curVal = tmpCurve.Points[iPt].Y;
+ }
+
+ // if the current value is missing, then the rest of the stack is missing
+ if ( curVal == PointPair.Missing )
+ stack = PointPair.Missing;
+
+ // if the current curve is the target curve, save the values
+ if ( tmpCurve == curve )
+ {
+ lowVal = stack;
+// if ( curVal < 0 && stack == 0 )
+// {
+// stack = curVal;
+// lowVal = curVal;
+// hiVal = curVal;
+// }
+// else
+ hiVal = ( curVal == PointPair.Missing || stack == PointPair.Missing ) ?
+ PointPair.Missing : stack + curVal;
+ }
+
+ // sum all the curves to a single total. This includes both positive and
+ // negative values (unlike the bar stack type).
+ stack = ( curVal == PointPair.Missing || stack == PointPair.Missing ) ?
+ PointPair.Missing : stack + curVal;
+ }
+ }
+
+ if ( baseVal == PointPair.Missing || lowVal == PointPair.Missing ||
+ hiVal == PointPair.Missing )
+ return false;
+ else
+ return true;
+ }
+ // otherwise, the curve is not a stacked type (not a stacked bar or stacked line)
+ else
+ {
+ if ((!(curve is HiLowBarItem)) && (!(curve is ErrorBarItem)))
+ lowVal = 0;
+ else
+ lowVal = curve.Points[iPt].LowValue;
+
+ if ( baseAxis is XAxis || baseAxis is X2Axis )
+ hiVal = curve.Points[iPt].Y;
+ else
+ hiVal = curve.Points[iPt].X;
+ }
+
+ // Special Exception: Bars on log scales should always plot from the Min value upwards,
+ // since they can never be zero
+ if ( curve is BarItem && valueAxis._scale.IsLog && lowVal == 0 )
+ lowVal = valueAxis._scale._min;
+
+ if ( baseVal == PointPair.Missing || hiVal == PointPair.Missing ||
+ ( lowVal == PointPair.Missing && ( curve is ErrorBarItem ||
+ curve is HiLowBarItem ) ) )
+ return false;
+ else
+ return true;
+ }
+
+ /// <summary>
+ /// Calculate the user scale position of the center of the specified bar, using the
+ /// <see cref="Axis"/> as specified by <see cref="BarSettings.Base"/>. This method is
+ /// used primarily by the
+ /// <see cref="GraphPane.FindNearestPoint(PointF,out CurveItem,out int)"/> method in order to
+ /// determine the bar "location," which is defined as the center of the top of the individual bar.
+ /// </summary>
+ /// <param name="curve">The <see cref="CurveItem"/> representing the
+ /// bar of interest.</param>
+ /// <param name="barWidth">The width of each individual bar. This can be calculated using
+ /// the <see cref="CurveItem.GetBarWidth"/> method.</param>
+ /// <param name="iCluster">The cluster number for the bar of interest. This is the ordinal
+ /// position of the current point. That is, if a particular <see cref="CurveItem"/> has
+ /// 10 points, then a value of 3 would indicate the 4th point in the data array.</param>
+ /// <param name="val">The actual independent axis value for the bar of interest.</param>
+ /// <param name="iOrdinal">The ordinal position of the <see cref="CurveItem"/> of interest.
+ /// That is, the first bar series is 0, the second is 1, etc. Note that this applies only
+ /// to the bars. If a graph includes both bars and lines, then count only the bars.</param>
+ /// <returns>A user scale value position of the center of the bar of interest.</returns>
+ public double BarCenterValue( CurveItem curve, float barWidth, int iCluster,
+ double val, int iOrdinal )
+ {
+ Axis baseAxis = curve.BaseAxis( _pane );
+ if ( curve is ErrorBarItem || curve is HiLowBarItem ||
+ curve is OHLCBarItem || curve is JapaneseCandleStickItem )
+ {
+ if ( baseAxis._scale.IsAnyOrdinal && iCluster >= 0 && !curve.IsOverrideOrdinal )
+ return (double) iCluster + 1.0;
+ else
+ return val;
+ }
+ else
+ {
+ float clusterWidth = _pane._barSettings.GetClusterWidth();
+ float clusterGap = _pane._barSettings.MinClusterGap * barWidth;
+ float barGap = barWidth * _pane._barSettings.MinBarGap;
+
+ if ( curve.IsBar && _pane._barSettings.Type != BarType.Cluster )
+ iOrdinal = 0;
+
+ float centerPix = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, iCluster, val )
+ - clusterWidth / 2.0F + clusterGap / 2.0F +
+ iOrdinal * ( barWidth + barGap ) + 0.5F * barWidth;
+ return baseAxis.Scale.ReverseTransform( centerPix );
+ }
+ }
+ }
+}
diff --git a/ZedGraph/X2Axis.cs b/ZedGraph/X2Axis.cs
new file mode 100644
index 0000000..63b192a
--- /dev/null
+++ b/ZedGraph/X2Axis.cs
@@ -0,0 +1,259 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2007 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// <see cref="X2Axis"/> inherits from <see cref="Axis"/>, and defines the
+ /// special characteristics of a horizontal axis, specifically located at
+ /// the top of the <see cref="Chart.Rect"/> of the <see cref="GraphPane"/>
+ /// object
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2007-04-16 00:03:07 $ </version>
+ [Serializable]
+ public class X2Axis : Axis, ICloneable, ISerializable
+ {
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="X2Axis"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ // Default X2 Axis properties
+ /// <summary>
+ /// The default display mode for the <see cref="X2Axis"/>
+ /// (<see cref="Axis.IsVisible"/> property). true to display the scale
+ /// values, title, tic marks, false to hide the axis entirely.
+ /// </summary>
+ public static bool IsVisible = false;
+ /// <summary>
+ /// Determines if a line will be drawn at the zero value for the
+ /// <see cref="X2Axis"/>, that is, a line that
+ /// divides the negative values from positive values.
+ /// <seealso cref="MajorGrid.IsZeroLine"/>.
+ /// </summary>
+ public static bool IsZeroLine = false;
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="X2Axis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class
+ /// </summary>
+ public X2Axis()
+ : this( "X2 Axis" )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="X2Axis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class, except
+ /// for the axis title
+ /// </summary>
+ /// <param name="title">The <see cref="Axis.Title"/> for this axis</param>
+ public X2Axis( string title )
+ : base( title )
+ {
+ _isVisible = Default.IsVisible;
+ _majorGrid._isZeroLine = Default.IsZeroLine;
+ _scale._fontSpec.Angle = 180F;
+ _title._fontSpec.Angle = 180F;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The X2Axis object from which to copy</param>
+ public X2Axis( X2Axis rhs )
+ : base( rhs )
+ {
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public X2Axis Clone()
+ {
+ return new X2Axis( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 11;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected X2Axis( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Setup the Transform Matrix to handle drawing of this <see cref="X2Axis"/>
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void SetTransformMatrix( Graphics g, GraphPane pane, float scaleFactor )
+ {
+ // Move the origin to the TopLeft of the ChartRect, which is the left
+ // side of the X2 axis (facing from the label side)
+ g.TranslateTransform( pane.Chart._rect.Right, pane.Chart._rect.Top );
+ //g.ScaleTransform( 1.0f, -1.0f );
+ // rotate so this axis is in the right-left direction
+ g.RotateTransform( 180 );
+ }
+
+ /// <summary>
+ /// Determines if this <see cref="Axis" /> object is a "primary" one.
+ /// </summary>
+ /// <remarks>
+ /// The primary axes are the <see cref="XAxis" /> (always),
+ /// the <see cref="X2Axis" /> (always), the first
+ /// <see cref="YAxis" /> in the <see cref="GraphPane.YAxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0), and the first
+ /// <see cref="Y2Axis" /> in the <see cref="GraphPane.Y2AxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0). Note that
+ /// <see cref="GraphPane.YAxis" /> and <see cref="GraphPane.Y2Axis" />
+ /// always reference the primary axes.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>true for a primary <see cref="Axis" /> (for the <see cref="X2Axis" />,
+ /// this is always true), false otherwise</returns>
+ override internal bool IsPrimary( GraphPane pane )
+ {
+ return this == pane.X2Axis;
+ }
+
+ /// <summary>
+ /// Calculate the "shift" size, in pixels, in order to shift the axis from its default
+ /// location to the value specified by <see cref="Axis.Cross"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>The shift amount measured in pixels</returns>
+ internal override float CalcCrossShift( GraphPane pane )
+ {
+ double effCross = EffectiveCrossValue( pane );
+
+ if ( !_crossAuto )
+ return pane.YAxis.Scale.Transform( effCross ) - pane.YAxis.Scale._maxPix;
+ else
+ return 0;
+ }
+ /*
+ override internal bool IsCrossed( GraphPane pane )
+ {
+ return !this.crossAuto && this.cross > pane.YAxis.Min && this.cross < pane.YAxis.Max;
+ }
+ */
+ /// <summary>
+ /// Gets the "Cross" axis that corresponds to this axis.
+ /// </summary>
+ /// <remarks>
+ /// The cross axis is the axis which determines the of this Axis when the
+ /// <see cref="Axis.Cross" >Axis.Cross</see> property is used. The
+ /// cross axis for any <see cref="XAxis" /> or <see cref="X2Axis" />
+ /// is always the primary <see cref="YAxis" />, and
+ /// the cross axis for any <see cref="YAxis" /> or <see cref="Y2Axis" /> is
+ /// always the primary <see cref="XAxis" />.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ override public Axis GetCrossAxis( GraphPane pane )
+ {
+ return pane.YAxis;
+ }
+
+ // override internal float GetMinPix( GraphPane pane )
+ // {
+ // return pane.Chart._rect.Left;
+ // }
+
+ #endregion
+ }
+}
+
+
+
diff --git a/ZedGraph/XAxis.cs b/ZedGraph/XAxis.cs
new file mode 100644
index 0000000..d58ae9f
--- /dev/null
+++ b/ZedGraph/XAxis.cs
@@ -0,0 +1,254 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// <see cref="XAxis"/> inherits from <see cref="Axis"/>, and defines the
+ /// special characteristics of a horizontal axis, specifically located at
+ /// the bottom of the <see cref="Chart.Rect"/> of the <see cref="GraphPane"/>
+ /// object
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.16 $ $Date: 2007-04-16 00:03:02 $ </version>
+ [Serializable]
+ public class XAxis : Axis, ICloneable, ISerializable
+ {
+
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="XAxis"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ // Default X Axis properties
+ /// <summary>
+ /// The default display mode for the <see cref="XAxis"/>
+ /// (<see cref="Axis.IsVisible"/> property). true to display the scale
+ /// values, title, tic marks, false to hide the axis entirely.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// Determines if a line will be drawn at the zero value for the
+ /// <see cref="XAxis"/>, that is, a line that
+ /// divides the negative values from positive values.
+ /// <seealso cref="MajorGrid.IsZeroLine"/>.
+ /// </summary>
+ public static bool IsZeroLine = false;
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="XAxis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class
+ /// </summary>
+ public XAxis()
+ : this( "X Axis" )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="XAxis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class, except
+ /// for the axis title
+ /// </summary>
+ /// <param name="title">The <see cref="Axis.Title"/> for this axis</param>
+ public XAxis( string title )
+ : base( title )
+ {
+ _isVisible = Default.IsVisible;
+ _majorGrid._isZeroLine = Default.IsZeroLine;
+ _scale._fontSpec.Angle = 0F;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The XAxis object from which to copy</param>
+ public XAxis( XAxis rhs )
+ : base( rhs )
+ {
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public XAxis Clone()
+ {
+ return new XAxis( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected XAxis( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Setup the Transform Matrix to handle drawing of this <see cref="XAxis"/>
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void SetTransformMatrix( Graphics g, GraphPane pane, float scaleFactor )
+ {
+ // Move the origin to the BottomLeft of the ChartRect, which is the left
+ // side of the X axis (facing from the label side)
+ g.TranslateTransform( pane.Chart._rect.Left, pane.Chart._rect.Bottom );
+ }
+
+ /// <summary>
+ /// Determines if this <see cref="Axis" /> object is a "primary" one.
+ /// </summary>
+ /// <remarks>
+ /// The primary axes are the <see cref="XAxis" /> (always), the first
+ /// <see cref="YAxis" /> in the <see cref="GraphPane.YAxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0), and the first
+ /// <see cref="Y2Axis" /> in the <see cref="GraphPane.Y2AxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0). Note that
+ /// <see cref="GraphPane.YAxis" /> and <see cref="GraphPane.Y2Axis" />
+ /// always reference the primary axes.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>true for a primary <see cref="Axis" /> (for the <see cref="XAxis" />,
+ /// this is always true), false otherwise</returns>
+ override internal bool IsPrimary( GraphPane pane )
+ {
+ return this == pane.XAxis;
+ }
+
+ /// <summary>
+ /// Calculate the "shift" size, in pixels, in order to shift the axis from its default
+ /// location to the value specified by <see cref="Axis.Cross"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>The shift amount measured in pixels</returns>
+ internal override float CalcCrossShift( GraphPane pane )
+ {
+ double effCross = EffectiveCrossValue( pane );
+
+ if ( !_crossAuto )
+ return pane.YAxis.Scale.Transform( effCross ) - pane.YAxis.Scale._maxPix;
+ else
+ return 0;
+ }
+ /*
+ override internal bool IsCrossed( GraphPane pane )
+ {
+ return !this.crossAuto && this.cross > pane.YAxis.Min && this.cross < pane.YAxis.Max;
+ }
+ */
+ /// <summary>
+ /// Gets the "Cross" axis that corresponds to this axis.
+ /// </summary>
+ /// <remarks>
+ /// The cross axis is the axis which determines the of this Axis when the
+ /// <see cref="Axis.Cross" >Axis.Cross</see> property is used. The
+ /// cross axis for any <see cref="XAxis" /> or <see cref="X2Axis" />
+ /// is always the primary <see cref="YAxis" />, and
+ /// the cross axis for any <see cref="YAxis" /> or <see cref="Y2Axis" /> is
+ /// always the primary <see cref="XAxis" />.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ override public Axis GetCrossAxis( GraphPane pane )
+ {
+ return pane.YAxis;
+ }
+
+// override internal float GetMinPix( GraphPane pane )
+// {
+// return pane.Chart._rect.Left;
+// }
+
+ #endregion
+ }
+}
+
+
+
diff --git a/ZedGraph/XDate.cs b/ZedGraph/XDate.cs
new file mode 100644
index 0000000..cd70363
--- /dev/null
+++ b/ZedGraph/XDate.cs
@@ -0,0 +1,1732 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+
+namespace ZedGraph
+{
+
+ /// <summary>
+ /// This struct encapsulates a date and time value, and handles associated
+ /// calculations and conversions between various formats.
+ /// </summary>
+ /// <remarks>
+ /// This format stored as a double value representing days since a reference date
+ /// (XL date 0.0 is December 30, 1899 at 00:00 hrs).
+ /// Negative values are permissible, and the
+ /// range of valid dates is from noon on January 1st, 4713 B.C. forward. Internally, the
+ /// date calculations are done using Astronomical Julian Day numbers. The Astronomical Julian
+ /// Day number is defined as the number of days since noon on January 1st, 4713 B.C.
+ /// (also referred to as 12:00 on January 1, -4712).
+ /// NOTE: MS Excel actually has an error in the Serial Date calculations because it
+ /// errantly assumes 1900 is a leap year. The XDate calculations do not have this same
+ /// error. Therefore, XDate and Excel Date Serial values are 1 day different up until
+ /// the date value of 60 (in Excel, this is February 29th, 1900, and in XDate, this is
+ /// February 28th, 1900). At a value of 61 (March 1st, 1900) or greater, they agree with
+ /// eachother.
+ /// </remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.23 $ $Date: 2007-11-11 06:56:34 $ </version>
+ public struct XDate : IComparable
+ {
+ #region Fields & Constants
+ // =========================================================================
+ // Internal Variables
+ // =========================================================================
+
+ /// <summary>
+ /// The actual date value in MS Excel format. This is the only data field in
+ /// the <see cref="XDate"/> struct.
+ /// </summary>
+ private double _xlDate;
+
+ /// <summary>
+ /// The Astronomical Julian Day number that corresponds to XL Date 0.0
+ /// </summary>
+ public const double XLDay1 = 2415018.5;
+
+ /// <summary>
+ /// The minimum valid Julian Day, which corresponds to January 1st, 4713 B.C.
+ /// </summary>
+ public const double JulDayMin = 0.0;
+ /// <summary>
+ /// The maximum valid Julian Day, which corresponds to December 31st, 9999 A.D.
+ /// </summary>
+ public const double JulDayMax = 5373483.5;
+ /// <summary>
+ /// The minimum valid Excel Day, which corresponds to January 1st, 4713 B.C.
+ /// </summary>
+ public const double XLDayMin = JulDayMin - XLDay1;
+ /// <summary>
+ /// The maximum valid Excel Day, which corresponds to December 31st, 9999 A.D.
+ /// </summary>
+ public const double XLDayMax = JulDayMax - XLDay1;
+
+ /// <summary>
+ /// The number of months in a year
+ /// </summary>
+ public const double MonthsPerYear = 12.0;
+ /// <summary>
+ /// The number of hours in a day
+ /// </summary>
+ public const double HoursPerDay = 24.0;
+ /// <summary>
+ /// The number of minutes in an hour
+ /// </summary>
+ public const double MinutesPerHour = 60.0;
+ /// <summary>
+ /// The number of seconds in a minute
+ /// </summary>
+ public const double SecondsPerMinute = 60.0;
+ /// <summary>
+ /// The number of minutes in a day
+ /// </summary>
+ public const double MinutesPerDay = 1440.0;
+ /// <summary>
+ /// The number of seconds in a day
+ /// </summary>
+ public const double SecondsPerDay = 86400.0;
+ /// <summary>
+ /// The number of milliseconds in a second
+ /// </summary>
+ public const double MillisecondsPerSecond = 1000.0;
+ /// <summary>
+ /// The number of milliseconds in a day
+ /// </summary>
+ public const double MillisecondsPerDay = 86400000.0;
+ /// <summary>
+ /// The default format string to be used in <see cref="ToString()"/> when
+ /// no format is provided
+ /// </summary>
+// public const string DefaultFormatStr = "&d-&mmm-&yy &hh:&nn";
+ public const string DefaultFormatStr = "g";
+ #endregion
+
+ #region Constructors
+ // =========================================================================
+ // Constructors
+ // =========================================================================
+
+ /// <summary>
+ /// Construct a date class from an XL date value.
+ /// </summary>
+ /// <param name="xlDate">
+ /// An XL Date value in floating point double format
+ /// </param>
+ public XDate( double xlDate )
+ {
+ _xlDate = xlDate;
+ }
+
+ /// <summary>
+ /// Construct a date class from a <see cref="DateTime"/> struct.
+ /// </summary>
+ /// <param name="dateTime">
+ /// A <see cref="DateTime"/> struct containing the initial date information.
+ /// </param>
+ public XDate( DateTime dateTime )
+ {
+ _xlDate = CalendarDateToXLDate( dateTime.Year, dateTime.Month,
+ dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second,
+ dateTime.Millisecond );
+ }
+
+ /// <summary>
+ /// Construct a date class from a calendar date (year, month, day). Assumes the time
+ /// of day is 00:00 hrs
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.
+ /// It is permissible to have day numbers outside of the 1-31 range,
+ /// which will rollover to the previous or next month and year.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August. It is permissible to have months outside of the 1-12 range,
+ /// which will rollover to the previous or next year.</param>
+ public XDate( int year, int month, int day )
+ {
+ _xlDate = CalendarDateToXLDate( year, month, day, 0, 0, 0 );
+ }
+
+ /// <summary>
+ /// Construct a date class from a calendar date and time (year, month, day, hour, minute,
+ /// second).
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.
+ /// It is permissible to have day numbers outside of the 1-31 range,
+ /// which will rollover to the previous or next month and year.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August. It is permissible to have months outside of the 1-12 range,
+ /// which will rollover to the previous or next year.</param>
+ /// <param name="hour">An integer value for the hour of the day, e.g. 15.
+ /// It is permissible to have hour values outside the 0-23 range, which
+ /// will rollover to the previous or next day.</param>
+ /// <param name="minute">An integer value for the minute, e.g. 45.
+ /// It is permissible to have hour values outside the 0-59 range, which
+ /// will rollover to the previous or next hour.</param>
+ /// <param name="second">An integer value for the second, e.g. 35.
+ /// It is permissible to have second values outside the 0-59 range, which
+ /// will rollover to the previous or next minute.</param>
+ public XDate( int year, int month, int day, int hour, int minute, int second )
+ {
+ _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
+ }
+
+ /// <summary>
+ /// Construct a date class from a calendar date and time (year, month, day, hour, minute,
+ /// second), where seconds is a <see cref="System.Double" /> value (allowing fractional seconds).
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.
+ /// It is permissible to have day numbers outside of the 1-31 range,
+ /// which will rollover to the previous or next month and year.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August. It is permissible to have months outside of the 1-12 range,
+ /// which will rollover to the previous or next year.</param>
+ /// <param name="hour">An integer value for the hour of the day, e.g. 15.
+ /// It is permissible to have hour values outside the 0-23 range, which
+ /// will rollover to the previous or next day.</param>
+ /// <param name="minute">An integer value for the minute, e.g. 45.
+ /// It is permissible to have hour values outside the 0-59 range, which
+ /// will rollover to the previous or next hour.</param>
+ /// <param name="second">A double value for the second, e.g. 35.75.
+ /// It is permissible to have second values outside the 0-59 range, which
+ /// will rollover to the previous or next minute.</param>
+ public XDate( int year, int month, int day, int hour, int minute, double second )
+ {
+ _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
+ }
+
+ /// <summary>
+ /// Construct a date class from a calendar date and time (year, month, day, hour, minute,
+ /// second, millisecond).
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.
+ /// It is permissible to have day numbers outside of the 1-31 range,
+ /// which will rollover to the previous or next month and year.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August. It is permissible to have months outside of the 1-12 range,
+ /// which will rollover to the previous or next year.</param>
+ /// <param name="hour">An integer value for the hour of the day, e.g. 15.
+ /// It is permissible to have hour values outside the 0-23 range, which
+ /// will rollover to the previous or next day.</param>
+ /// <param name="minute">An integer value for the minute, e.g. 45.
+ /// It is permissible to have hour values outside the 0-59 range, which
+ /// will rollover to the previous or next hour.</param>
+ /// <param name="second">An integer value for the second, e.g. 35.
+ /// It is permissible to have second values outside the 0-59 range, which
+ /// will rollover to the previous or next minute.</param>
+ /// <param name="millisecond">An integer value for the millisecond, e.g. 632.
+ /// It is permissible to have millisecond values outside the 0-999 range, which
+ /// will rollover to the previous or next second.</param>
+ public XDate( int year, int month, int day, int hour, int minute, int second, int millisecond )
+ {
+ _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second, millisecond );
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The GraphPane object from which to copy</param>
+ public XDate( XDate rhs )
+ {
+ _xlDate = rhs._xlDate;
+ }
+/*
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public XDate Clone()
+ {
+ return new XDate( this );
+ }
+*/
+
+ #endregion
+
+ #region Properties
+ // =========================================================================
+ // Properties
+ // =========================================================================
+
+ /// <summary>
+ /// Gets or sets the date value for this item in MS Excel format.
+ /// </summary>
+ public double XLDate
+ {
+ get { return _xlDate; }
+ set { _xlDate = value; }
+ }
+
+ /// <summary>
+ /// Returns true if this <see cref="XDate" /> struct is in the valid date range
+ /// </summary>
+ public bool IsValidDate
+ {
+ get { return _xlDate >= XLDayMin && _xlDate <= XLDayMax; }
+ }
+
+ /// <summary>
+ /// Gets or sets the date value for this item in .Net DateTime format.
+ /// </summary>
+ public DateTime DateTime
+ {
+ get { return XLDateToDateTime( _xlDate ); }
+ set { _xlDate = DateTimeToXLDate( value ); }
+ }
+
+ /// <summary>
+ /// Gets or sets the date value for this item in Julain day format. This is the
+ /// Astronomical Julian Day number, so a value of 0.0 corresponds to noon GMT on
+ /// January 1st, -4712. Thus, Julian Day number 2,400,000.0 corresponds to
+ /// noon GMT on November 16, 1858.
+ /// </summary>
+ public double JulianDay
+ {
+ get { return XLDateToJulianDay( _xlDate ); }
+ set { _xlDate = JulianDayToXLDate( value ); }
+ }
+
+ /// <summary>
+ /// Gets or sets the decimal year number (i.e., 1997.345) corresponding to this item.
+ /// </summary>
+ public double DecimalYear
+ {
+ get { return XLDateToDecimalYear( _xlDate ); }
+ set { _xlDate = DecimalYearToXLDate( value ); }
+ }
+ #endregion
+
+ #region Get/Set Date Methods
+
+ /// <summary>
+ /// Returns true if the specified date value is in the valid range
+ /// </summary>
+ /// <param name="xlDate">The XL date value to be verified for validity</param>
+ /// <returns>true for a valid date, false otherwise</returns>
+ private static bool CheckValidDate( double xlDate )
+ {
+ return xlDate >= XLDayMin && xlDate <= XLDayMax;
+ }
+
+ /// <summary>
+ /// Take the specified date, and bound it to the valid date range for the XDate struct.
+ /// </summary>
+ /// <param name="xlDate">The date to be bounded</param>
+ /// <returns>An XLDate value that lies between the minimum and maximum valid date ranges
+ /// (see <see cref="XLDayMin" /> and <see cref="XLDayMax" />)</returns>
+ public static double MakeValidDate( double xlDate )
+ {
+ if ( xlDate < XLDayMin )
+ xlDate = XLDayMin;
+ if ( xlDate > XLDayMax )
+ xlDate = XLDayMax;
+ return xlDate;
+ }
+
+ /// <summary>
+ /// Get the calendar date (year, month, day) corresponding to this instance.
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August.</param>
+ public void GetDate( out int year, out int month, out int day )
+ {
+ int hour, minute, second;
+
+ XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
+ }
+
+ /// <summary>
+ /// Set the calendar date (year, month, day) of this instance.
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August.</param>
+ public void SetDate( int year, int month, int day )
+ {
+ _xlDate = CalendarDateToXLDate( year, month, day, 0, 0, 0 );
+ }
+
+ /// <summary>
+ /// Get the calendar date (year, month, day, hour, minute, second) corresponding
+ /// to this instance.
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August.</param>
+ /// <param name="hour">An integer value for the hour of the day, e.g. 15.</param>
+ /// <param name="minute">An integer value for the minute, e.g. 45.</param>
+ /// <param name="second">An integer value for the second, e.g. 35.</param>
+ public void GetDate( out int year, out int month, out int day,
+ out int hour, out int minute, out int second )
+ {
+ XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
+ }
+
+ /// <summary>
+ /// Set the calendar date (year, month, day, hour, minute, second) of this instance.
+ /// </summary>
+ /// <param name="year">An integer value for the year, e.g., 1995.</param>
+ /// <param name="day">An integer value for the day of the month, e.g., 23.</param>
+ /// <param name="month">An integer value for the month of the year, e.g.,
+ /// 8 for August.</param>
+ /// <param name="hour">An integer value for the hour of the day, e.g. 15.</param>
+ /// <param name="minute">An integer value for the minute, e.g. 45.</param>
+ /// <param name="second">An integer value for the second, e.g. 35.</param>
+ public void SetDate( int year, int month, int day, int hour, int minute, int second )
+ {
+ _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
+ }
+
+ /// <summary>
+ /// Get the day of year value (241.345 means the 241st day of the year)
+ /// corresponding to this instance.
+ /// </summary>
+ /// <returns>The day of the year in floating point double format.</returns>
+ public double GetDayOfYear()
+ {
+ return XLDateToDayOfYear( _xlDate );
+ }
+ #endregion
+
+ #region Date Conversion Methods
+ // =========================================================================
+ // Conversion Routines
+ // =========================================================================
+
+ /// <summary>
+ /// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second),
+ /// first normalizing all input data values.
+ /// </summary>
+ /// <remarks>
+ /// The Calendar date is always based on the Gregorian Calendar. Note that the Gregorian calendar is really
+ /// only valid from October 15, 1582 forward. The countries that adopted the Gregorian calendar
+ /// first did so on October 4, 1582, so that the next day was October 15, 1582. Prior to that time
+ /// the Julian Calendar was used. However, Prior to March 1, 4 AD the treatment of leap years was
+ /// inconsistent, and prior to 45 BC the Julian Calendar did not exist. The <see cref="XDate"/>
+ /// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The
+ /// <see cref="ToString(double,string)"/> method will just append a "(BC)" notation to the end of any dates
+ /// prior to 1 AD, since the <see cref="DateTime"/> struct throws an exception when formatting earlier dates.
+ /// </remarks>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The integer millisecond value (e.g., 374 for 374 milliseconds past the second).
+ /// </param>
+ /// <returns>The corresponding XL date, expressed in double floating point format</returns>
+ public static double CalendarDateToXLDate( int year, int month, int day,
+ int hour, int minute, int second, int millisecond )
+ {
+ // Normalize the data to allow for negative and out of range values
+ // In this way, setting month to zero would be December of the previous year,
+ // setting hour to 24 would be the first hour of the next day, etc.
+ //double dsec = second + (double) millisecond / MillisecondsPerSecond;
+ double ms = millisecond;
+ NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute, ref second,
+ ref ms );
+
+ return _CalendarDateToXLDate( year, month, day, hour, minute, second, ms );
+ }
+
+ /// <summary>
+ /// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second),
+ /// first normalizing all input data values.
+ /// </summary>
+ /// <remarks>
+ /// The Calendar date is always based on the Gregorian Calendar. Note that the Gregorian calendar is really
+ /// only valid from October 15, 1582 forward. The countries that adopted the Gregorian calendar
+ /// first did so on October 4, 1582, so that the next day was October 15, 1582. Prior to that time
+ /// the Julian Calendar was used. However, Prior to March 1, 4 AD the treatment of leap years was
+ /// inconsistent, and prior to 45 BC the Julian Calendar did not exist. The <see cref="XDate"/>
+ /// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The
+ /// <see cref="ToString(double,string)"/> method will just append a "(BC)" notation to the end of any dates
+ /// prior to 1 AD, since the <see cref="DateTime"/> struct throws an exception when formatting earlier dates.
+ /// </remarks>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <returns>The corresponding XL date, expressed in double floating point format</returns>
+ public static double CalendarDateToXLDate( int year, int month, int day,
+ int hour, int minute, int second )
+ {
+ // Normalize the data to allow for negative and out of range values
+ // In this way, setting month to zero would be December of the previous year,
+ // setting hour to 24 would be the first hour of the next day, etc.
+ double ms = 0;
+ NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute,
+ ref second, ref ms );
+
+ return _CalendarDateToXLDate( year, month, day, hour, minute, second, ms );
+ }
+
+ /// <summary>
+ /// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second),
+ /// first normalizing all input data values. The seconds value is a double type, allowing fractional
+ /// seconds.
+ /// </summary>
+ /// <remarks>
+ /// The Calendar date is always based on the Gregorian Calendar. Note that the Gregorian calendar is really
+ /// only valid from October 15, 1582 forward. The countries that adopted the Gregorian calendar
+ /// first did so on October 4, 1582, so that the next day was October 15, 1582. Prior to that time
+ /// the Julian Calendar was used. However, Prior to March 1, 4 AD the treatment of leap years was
+ /// inconsistent, and prior to 45 BC the Julian Calendar did not exist. The <see cref="XDate"/>
+ /// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The
+ /// <see cref="ToString(double,string)"/> method will just append a "(BC)" notation to the end of any dates
+ /// prior to 1 AD, since the <see cref="DateTime"/> struct throws an exception when formatting earlier dates.
+ /// </remarks>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The double second value (e.g., 42.3 for 42.3 seconds past the minute).
+ /// </param>
+ /// <returns>The corresponding XL date, expressed in double floating point format</returns>
+ public static double CalendarDateToXLDate( int year, int month, int day,
+ int hour, int minute, double second )
+ {
+ // Normalize the data to allow for negative and out of range values
+ // In this way, setting month to zero would be December of the previous year,
+ // setting hour to 24 would be the first hour of the next day, etc.
+ int sec = (int)second;
+ double ms = ( second - sec ) * MillisecondsPerSecond;
+ NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute, ref sec,
+ ref ms );
+
+ return _CalendarDateToXLDate( year, month, day, hour, minute, sec, ms );
+ }
+
+ /// <summary>
+ /// Calculate an Astronomical Julian Day number from the specified Calendar date
+ /// (year, month, day, hour, minute, second), first normalizing all input data values
+ /// </summary>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <returns>The corresponding Astronomical Julian Day number, expressed in double
+ /// floating point format</returns>
+ public static double CalendarDateToJulianDay( int year, int month, int day,
+ int hour, int minute, int second )
+ {
+ // Normalize the data to allow for negative and out of range values
+ // In this way, setting month to zero would be December of the previous year,
+ // setting hour to 24 would be the first hour of the next day, etc.
+ double ms = 0;
+ NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute,
+ ref second, ref ms );
+
+ return _CalendarDateToJulianDay( year, month, day, hour, minute, second, ms );
+ }
+
+ /// <summary>
+ /// Calculate an Astronomical Julian Day number from the specified Calendar date
+ /// (year, month, day, hour, minute, second), first normalizing all input data values
+ /// </summary>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The integer second value (e.g., 325 for 325 milliseconds past the minute).
+ /// </param>
+ /// <returns>The corresponding Astronomical Julian Day number, expressed in double
+ /// floating point format</returns>
+ public static double CalendarDateToJulianDay( int year, int month, int day,
+ int hour, int minute, int second, int millisecond )
+ {
+ // Normalize the data to allow for negative and out of range values
+ // In this way, setting month to zero would be December of the previous year,
+ // setting hour to 24 would be the first hour of the next day, etc.
+ double ms = millisecond;
+
+ NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute,
+ ref second, ref ms );
+
+ return _CalendarDateToJulianDay( year, month, day, hour, minute, second, ms );
+ }
+
+ /// <summary>
+ /// Normalize a set of Calendar date values (year, month, day, hour, minute, second) to make sure
+ /// that month is between 1 and 12, hour is between 0 and 23, etc.
+ /// </summary>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second).
+ /// </param>
+ private static void NormalizeCalendarDate( ref int year, ref int month, ref int day,
+ ref int hour, ref int minute, ref int second,
+ ref double millisecond )
+ {
+ // Normalize the data to allow for negative and out of range values
+ // In this way, setting month to zero would be December of the previous year,
+ // setting hour to 24 would be the first hour of the next day, etc.
+
+ // Normalize the milliseconds and carry over to seconds
+ int carry = (int)Math.Floor( millisecond / MillisecondsPerSecond );
+ millisecond -= carry * (int)MillisecondsPerSecond;
+ second += carry;
+
+ // Normalize the seconds and carry over to minutes
+ carry = (int)Math.Floor( second / SecondsPerMinute );
+ second -= carry * (int)SecondsPerMinute;
+ minute += carry;
+
+ // Normalize the minutes and carry over to hours
+ carry = (int) Math.Floor( (double) minute / MinutesPerHour );
+ minute -= carry * (int) MinutesPerHour;
+ hour += carry;
+
+ // Normalize the hours and carry over to days
+ carry = (int) Math.Floor( (double) hour / HoursPerDay );
+ hour -= carry * (int) HoursPerDay;
+ day += carry;
+
+ // Normalize the months and carry over to years
+ carry = (int) Math.Floor( (double) month / MonthsPerYear );
+ month -= carry * (int) MonthsPerYear;
+ year += carry;
+ }
+
+ /// <summary>
+ /// Calculate an XL date from the specified Calendar date (year, month, day, hour, minute, second).
+ /// This is the internal trusted version, where all values are assumed to be legitimate
+ /// ( month is between 1 and 12, minute is between 0 and 59, etc. )
+ /// </summary>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second).
+ /// </param>
+ /// <returns>The corresponding XL date, expressed in double floating point format</returns>
+ private static double _CalendarDateToXLDate( int year, int month, int day, int hour,
+ int minute, int second, double millisecond )
+ {
+ return JulianDayToXLDate( _CalendarDateToJulianDay( year, month, day, hour, minute,
+ second, millisecond ) );
+ }
+
+ /// <summary>
+ /// Calculate an Astronomical Julian Day Number from the specified Calendar date
+ /// (year, month, day, hour, minute, second).
+ /// This is the internal trusted version, where all values are assumed to be legitimate
+ /// ( month is between 1 and 12, minute is between 0 and 59, etc. )
+ /// </summary>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second).
+ /// </param>
+ /// <returns>The corresponding Astronomical Julian Day number, expressed in double
+ /// floating point format</returns>
+ private static double _CalendarDateToJulianDay( int year, int month, int day, int hour,
+ int minute, int second, double millisecond )
+ {
+ // Taken from http://www.srrb.noaa.gov/highlights/sunrise/program.txt
+ // routine calcJD()
+
+ if ( month <= 2 )
+ {
+ year -= 1;
+ month += 12;
+ }
+
+ double A = Math.Floor( (double) year / 100.0 );
+ double B = 2 - A + Math.Floor( A / 4.0 );
+
+ return Math.Floor( 365.25 * ( (double) year + 4716.0 ) ) +
+ Math.Floor( 30.6001 * (double) ( month + 1 ) ) +
+ (double) day + B - 1524.5 +
+ hour / HoursPerDay + minute / MinutesPerDay + second / SecondsPerDay +
+ millisecond / MillisecondsPerDay;
+
+ }
+
+ /// <summary>
+ /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
+ /// the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ public static void XLDateToCalendarDate( double xlDate, out int year, out int month,
+ out int day, out int hour, out int minute, out int second )
+ {
+ double jDay = XLDateToJulianDay( xlDate );
+
+ JulianDayToCalendarDate( jDay, out year, out month, out day, out hour,
+ out minute, out second );
+ }
+
+ /// <summary>
+ /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
+ /// the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The integer millisecond value (e.g., 325 for 325 milliseconds past the second).
+ /// </param>
+ public static void XLDateToCalendarDate( double xlDate, out int year, out int month,
+ out int day, out int hour, out int minute, out int second, out int millisecond )
+ {
+ double jDay = XLDateToJulianDay( xlDate );
+
+ double ms;
+ JulianDayToCalendarDate( jDay, out year, out month, out day, out hour,
+ out minute, out second, out ms );
+ millisecond = (int)ms;
+ }
+
+ /// <summary>
+ /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
+ /// the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The double second value (e.g., 42.3 for 42.3 seconds past the minute).
+ /// </param>
+ public static void XLDateToCalendarDate( double xlDate, out int year, out int month,
+ out int day, out int hour, out int minute, out double second )
+ {
+ double jDay = XLDateToJulianDay( xlDate );
+
+ JulianDayToCalendarDate( jDay, out year, out month, out day, out hour,
+ out minute, out second );
+ }
+
+ /// <summary>
+ /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
+ /// the Astronomical Julian Day number
+ /// </summary>
+ /// <param name="jDay">
+ /// The Astronomical Julian Day number to be converted
+ /// </param>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ public static void JulianDayToCalendarDate( double jDay, out int year, out int month,
+ out int day, out int hour, out int minute, out int second )
+ {
+ double ms = 0;
+
+ JulianDayToCalendarDate( jDay, out year, out month,
+ out day, out hour, out minute, out second, out ms );
+ }
+
+ /// <summary>
+ /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
+ /// the Astronomical Julian Day number
+ /// </summary>
+ /// <param name="jDay">
+ /// The Astronomical Julian Day number to be converted
+ /// </param>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The double second value (e.g., 42.3 for 42.3 seconds past the minute).
+ /// </param>
+ public static void JulianDayToCalendarDate( double jDay, out int year, out int month,
+ out int day, out int hour, out int minute, out double second )
+ {
+ int sec;
+ double ms;
+
+ JulianDayToCalendarDate( jDay, out year, out month,
+ out day, out hour, out minute, out sec, out ms );
+
+ second = sec + ms / MillisecondsPerSecond;
+ }
+
+ /// <summary>
+ /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
+ /// the Astronomical Julian Day number
+ /// </summary>
+ /// <param name="jDay">
+ /// The Astronomical Julian Day number to be converted
+ /// </param>
+ /// <param name="year">
+ /// The integer year value (e.g., 1994).
+ /// </param>
+ /// <param name="month">
+ /// The integer month value (e.g., 7 for July).
+ /// </param>
+ /// <param name="day">
+ /// The integer day value (e.g., 19 for the 19th day of the month).
+ /// </param>
+ /// <param name="hour">
+ /// The integer hour value (e.g., 14 for 2:00 pm).
+ /// </param>
+ /// <param name="minute">
+ /// The integer minute value (e.g., 35 for 35 minutes past the hour).
+ /// </param>
+ /// <param name="second">
+ /// The integer second value (e.g., 42 for 42 seconds past the minute).
+ /// </param>
+ /// <param name="millisecond">
+ /// The <see cref="System.Double" /> millisecond value (e.g., 342.5 for 342.5 milliseconds past
+ /// the second).
+ /// </param>
+ public static void JulianDayToCalendarDate( double jDay, out int year, out int month,
+ out int day, out int hour, out int minute, out int second, out double millisecond )
+ {
+ // add 5 ten-thousandths of a second to the day fraction to avoid roundoff errors
+ jDay += 0.0005 / SecondsPerDay;
+
+ double z = Math.Floor( jDay + 0.5);
+ double f = jDay + 0.5 - z;
+
+ double alpha = Math.Floor( ( z - 1867216.25 ) / 36524.25 );
+ double A = z + 1.0 + alpha - Math.Floor( alpha / 4 );
+ double B = A + 1524.0;
+ double C = Math.Floor( ( B - 122.1 ) / 365.25 );
+ double D = Math.Floor( 365.25 * C );
+ double E = Math.Floor( ( B - D ) / 30.6001 );
+
+ day = (int) Math.Floor( B - D - Math.Floor( 30.6001 * E ) + f );
+ month = (int) ( ( E < 14.0 ) ? E - 1.0 : E - 13.0 );
+ year = (int) ( ( month > 2 ) ? C - 4716 : C - 4715 );
+
+ double fday = ( jDay - 0.5 ) - Math.Floor( jDay - 0.5 );
+
+ fday = ( fday - (long) fday ) * HoursPerDay;
+ hour = (int) fday;
+ fday = ( fday - (long) fday ) * MinutesPerHour;
+ minute = (int) fday;
+ fday = ( fday - (long) fday ) * SecondsPerMinute;
+ second = (int) fday;
+ fday = ( fday - (long) fday ) * MillisecondsPerSecond;
+ millisecond = fday;
+ }
+
+ /// <summary>
+ /// Calculate an Astronomical Julian Day number corresponding to the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <returns>The corresponding Astronomical Julian Day number, expressed in double
+ /// floating point format</returns>
+ public static double XLDateToJulianDay( double xlDate )
+ {
+ return xlDate + XLDay1;
+ }
+
+ /// <summary>
+ /// Calculate an XL Date corresponding to the specified Astronomical Julian Day number
+ /// </summary>
+ /// <param name="jDay">
+ /// The Astronomical Julian Day number in floating point double format.
+ /// </param>
+ /// <returns>The corresponding XL Date, expressed in double
+ /// floating point format</returns>
+ public static double JulianDayToXLDate( double jDay )
+ {
+ return jDay - XLDay1;
+ }
+
+ /// <summary>
+ /// Calculate a decimal year value (e.g., 1994.6523) corresponding to the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <returns>The corresponding decimal year value, expressed in double
+ /// floating point format</returns>
+ public static double XLDateToDecimalYear( double xlDate )
+ {
+ int year, month, day, hour, minute, second;
+
+ XLDateToCalendarDate( xlDate, out year, out month, out day, out hour, out minute, out second );
+
+ double jDay1 = CalendarDateToJulianDay( year, 1, 1, 0, 0, 0 );
+ double jDay2 = CalendarDateToJulianDay( year + 1, 1, 1, 0, 0, 0 );
+ double jDayMid = CalendarDateToJulianDay( year, month, day, hour, minute, second );
+
+
+ return (double) year + ( jDayMid - jDay1 ) / ( jDay2 - jDay1 );
+ }
+
+ /// <summary>
+ /// Calculate a decimal year value (e.g., 1994.6523) corresponding to the specified XL date
+ /// </summary>
+ /// <param name="yearDec">
+ /// The decimal year value in floating point double format.
+ /// </param>
+ /// <returns>The corresponding XL Date, expressed in double
+ /// floating point format</returns>
+ public static double DecimalYearToXLDate( double yearDec )
+ {
+ int year = (int) yearDec;
+
+ double jDay1 = CalendarDateToJulianDay( year, 1, 1, 0, 0, 0 );
+ double jDay2 = CalendarDateToJulianDay( year + 1, 1, 1, 0, 0, 0 );
+
+ return JulianDayToXLDate( ( yearDec - (double) year ) * ( jDay2 - jDay1 ) + jDay1 );
+ }
+
+ /// <summary>
+ /// Calculate a day-of-year value (e.g., 241.543 corresponds to the 241st day of the year)
+ /// corresponding to the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <returns>The corresponding day-of-year (DoY) value, expressed in double
+ /// floating point format</returns>
+ public static double XLDateToDayOfYear( double xlDate )
+ {
+ int year, month, day, hour, minute, second;
+ XLDateToCalendarDate( xlDate, out year, out month, out day,
+ out hour, out minute, out second );
+ return XLDateToJulianDay( xlDate ) - CalendarDateToJulianDay( year, 1, 1, 0, 0, 0 ) + 1.0;
+ }
+
+ /// <summary>
+ /// Calculate a day-of-week value (e.g., Sun=0, Mon=1, Tue=2, etc.)
+ /// corresponding to the specified XL date
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <returns>The corresponding day-of-week (DoW) value, expressed in integer format</returns>
+ public static int XLDateToDayOfWeek( double xlDate )
+ {
+ return (int) ( XLDateToJulianDay( xlDate ) + 1.5 ) % 7;
+ }
+
+ /// <summary>
+ /// Convert an XL date format to a .Net DateTime struct
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value in floating point double format.
+ /// </param>
+ /// <returns>The corresponding XL Date, expressed in double
+ /// floating point format</returns>
+ /// <returns>The corresponding date in the form of a .Net DateTime struct</returns>
+ public static DateTime XLDateToDateTime( double xlDate )
+ {
+ int year, month, day, hour, minute, second, millisecond;
+ XLDateToCalendarDate( xlDate, out year, out month, out day,
+ out hour, out minute, out second, out millisecond );
+ return new DateTime( year, month, day, hour, minute, second, millisecond );
+ }
+
+ /// <summary>
+ /// Convert a .Net DateTime struct to an XL Format date
+ /// </summary>
+ /// <param name="dt">
+ /// The date value in the form of a .Net DateTime struct
+ /// </param>
+ /// <returns>The corresponding XL Date, expressed in double
+ /// floating point format</returns>
+ public static double DateTimeToXLDate( DateTime dt )
+ {
+ return CalendarDateToXLDate( dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second,
+ dt.Millisecond );
+ }
+ #endregion
+
+ #region Date Math Methods
+ // =========================================================================
+ // Math Routines
+ // =========================================================================
+
+ /// <summary>
+ /// Add the specified number of milliseconds (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dMilliseconds">
+ /// The incremental number of milliseconds (negative or positive) in floating point double format.
+ /// </param>
+ public void AddMilliseconds( double dMilliseconds )
+ {
+ _xlDate += dMilliseconds / MillisecondsPerDay;
+ }
+
+ /// <summary>
+ /// Add the specified number of seconds (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dSeconds">
+ /// The incremental number of seconds (negative or positive) in floating point double format.
+ /// </param>
+ public void AddSeconds( double dSeconds )
+ {
+ _xlDate += dSeconds / SecondsPerDay;
+ }
+
+ /// <summary>
+ /// Add the specified number of minutes (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dMinutes">
+ /// The incremental number of minutes (negative or positive) in floating point double format.
+ /// </param>
+ public void AddMinutes( double dMinutes )
+ {
+ _xlDate += dMinutes / MinutesPerDay;
+ }
+
+ /// <summary>
+ /// Add the specified number of hours (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dHours">
+ /// The incremental number of hours (negative or positive) in floating point double format.
+ /// </param>
+ public void AddHours( double dHours )
+ {
+ _xlDate += dHours / HoursPerDay;
+ }
+
+ /// <summary>
+ /// Add the specified number of days (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dDays">
+ /// The incremental number of days (negative or positive) in floating point double format.
+ /// </param>
+ public void AddDays( double dDays )
+ {
+ _xlDate += dDays;
+ }
+
+ /// <summary>
+ /// Add the specified number of Months (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dMonths">
+ /// The incremental number of months (negative or positive) in floating point double format.
+ /// </param>
+ public void AddMonths( double dMonths )
+ {
+ int iMon = (int) dMonths;
+ double monFrac = Math.Abs( dMonths - (double) iMon );
+ int sMon = Math.Sign( dMonths );
+
+ int year, month, day, hour, minute, second;
+
+ XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
+ if ( iMon != 0 )
+ {
+ month += iMon;
+ _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
+ }
+
+ if ( sMon != 0 )
+ {
+ double xlDate2 = CalendarDateToXLDate( year, month+sMon, day, hour, minute, second );
+ _xlDate += (xlDate2 - _xlDate) * monFrac;
+ }
+ }
+
+ /// <summary>
+ /// Add the specified number of years (can be fractional) to the current XDate instance.
+ /// </summary>
+ /// <param name="dYears">
+ /// The incremental number of years (negative or positive) in floating point double format.
+ /// </param>
+ public void AddYears( double dYears )
+ {
+ int iYear = (int) dYears;
+ double yearFrac = Math.Abs( dYears - (double) iYear );
+ int sYear = Math.Sign( dYears );
+
+ int year, month, day, hour, minute, second;
+
+ XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
+ if ( iYear != 0 )
+ {
+ year += iYear;
+ _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
+ }
+
+ if ( sYear != 0 )
+ {
+ double xlDate2 = CalendarDateToXLDate( year+sYear, month, day, hour, minute, second );
+ _xlDate += (xlDate2 - _xlDate) * yearFrac;
+ }
+ }
+ #endregion
+
+ #region Operator Overload Methods
+ // =========================================================================
+ // Operator Overloads
+ // =========================================================================
+
+ /// <summary>
+ /// '-' operator overload. When two XDates are subtracted, the number of days between dates
+ /// is returned.
+ /// </summary>
+ /// <param name="lhs">The left-hand-side of the '-' operator (an XDate class)</param>
+ /// <param name="rhs">The right-hand-side of the '-' operator (an XDate class)</param>
+ /// <returns>The days between dates, expressed as a floating point double</returns>
+ public static double operator -( XDate lhs, XDate rhs )
+ {
+ return lhs.XLDate - rhs.XLDate;
+ }
+
+ /// <summary>
+ /// '-' operator overload. When a double value is subtracted from an XDate, the result is a
+ /// new XDate with the number of days subtracted.
+ /// </summary>
+ /// <param name="lhs">The left-hand-side of the '-' operator (an XDate class)</param>
+ /// <param name="rhs">The right-hand-side of the '-' operator (a double value)</param>
+ /// <returns>An XDate with the rhs number of days subtracted</returns>
+ public static XDate operator -( XDate lhs, double rhs )
+ {
+ lhs._xlDate -= rhs;
+ return lhs;
+ }
+
+ /// <summary>
+ /// '+' operator overload. When a double value is added to an XDate, the result is a
+ /// new XDate with the number of days added.
+ /// </summary>
+ /// <param name="lhs">The left-hand-side of the '-' operator (an XDate class)</param>
+ /// <param name="rhs">The right-hand-side of the '+' operator (a double value)</param>
+ /// <returns>An XDate with the rhs number of days added</returns>
+ public static XDate operator +( XDate lhs, double rhs )
+ {
+ lhs._xlDate += rhs;
+ return lhs;
+ }
+
+ /// <summary>
+ /// '++' operator overload. Increment the date by one day.
+ /// </summary>
+ /// <param name="xDate">The XDate struct on which to operate</param>
+ /// <returns>An XDate one day later than the specified date</returns>
+ public static XDate operator ++( XDate xDate )
+ {
+ xDate._xlDate += 1.0;
+ return xDate;
+ }
+
+ /// <summary>
+ /// '--' operator overload. Decrement the date by one day.
+ /// </summary>
+ /// <param name="xDate">The XDate struct on which to operate</param>
+ /// <returns>An XDate one day prior to the specified date</returns>
+ public static XDate operator --( XDate xDate )
+ {
+ xDate._xlDate -= 1.0;
+ return xDate;
+ }
+
+ /// <summary>
+ /// Implicit conversion from XDate to double (an XL Date).
+ /// </summary>
+ /// <param name="xDate">The XDate struct on which to operate</param>
+ /// <returns>A double floating point value representing the XL Date</returns>
+ public static implicit operator double( XDate xDate )
+ {
+ return xDate._xlDate;
+ }
+
+ /// <summary>
+ /// Implicit conversion from XDate to float (an XL Date).
+ /// </summary>
+ /// <param name="xDate">The XDate struct on which to operate</param>
+ /// <returns>A double floating point value representing the XL Date</returns>
+ public static implicit operator float( XDate xDate )
+ {
+ return (float) xDate._xlDate;
+ }
+
+ /// <summary>
+ /// Implicit conversion from double (an XL Date) to XDate.
+ /// </summary>
+ /// <param name="xlDate">The XDate struct on which to operate</param>
+ /// <returns>An XDate struct representing the specified xlDate value.</returns>
+ public static implicit operator XDate( double xlDate )
+ {
+ return new XDate( xlDate );
+ }
+
+ /// <summary>
+ /// Implicit conversion from XDate to <see cref="DateTime"/>.
+ /// </summary>
+ /// <param name="xDate">The XDate struct on which to operate</param>
+ /// <returns>A <see cref="DateTime"/> struct representing the specified xDate value.</returns>
+ public static implicit operator DateTime( XDate xDate )
+ {
+
+ return XLDateToDateTime( xDate );
+ }
+
+ /// <summary>
+ /// Implicit conversion from <see cref="DateTime"/> to <see cref="XDate"/>.
+ /// </summary>
+ /// <param name="dt">The <see cref="DateTime"/> struct on which to operate</param>
+ /// <returns>An <see cref="XDate"/> struct representing the specified DateTime value.</returns>
+ public static implicit operator XDate( DateTime dt )
+ {
+
+ return new XDate( DateTimeToXLDate( dt ) );
+ }
+ #endregion
+
+ #region General Overrides
+ // =========================================================================
+ // System Stuff
+ // =========================================================================
+
+ /// <summary>
+ /// Tests whether <param>obj</param> is either an <see cref="XDate"/> structure or
+ /// a double floating point value that is equal to the same date as this <c>XDate</c>
+ /// struct instance.
+ /// </summary>
+ /// <param name="obj">The object to compare for equality with this XDate instance.
+ /// This object should be either a type XDate or type double.</param>
+ /// <returns>Returns <c>true</c> if <param>obj</param> is the same date as this
+ /// instance; otherwise, <c>false</c></returns>
+ public override bool Equals( object obj )
+ {
+ if ( obj is XDate )
+ {
+ return ((XDate) obj)._xlDate == _xlDate;
+ }
+ else if ( obj is double )
+ {
+ return ((double) obj) == _xlDate;
+ }
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// Returns the hash code for this <see cref="XDate"/> structure. In this case, the
+ /// hash code is simply the equivalent hash code for the floating point double date value.
+ /// </summary>
+ /// <returns>An integer representing the hash code for this XDate value</returns>
+ public override int GetHashCode()
+ {
+ return _xlDate.GetHashCode();
+ }
+
+ /// <summary>
+ /// Compares one <see cref="XDate" /> object to another.
+ /// </summary>
+ /// <remarks>
+ /// This method will throw an exception if <paramref name="target"/> is not an
+ /// <see cref="XDate"/> object.
+ /// </remarks>
+ /// <param name="target">The second <see cref="XDate" /> object to be compared.</param>
+ /// <returns>zero if <paramref name="target" /> is equal to the current instance,
+ /// -1 if <paramref name="target"/> is less than the current instance, and
+ /// 1 if <paramref name="target"/> is greater than the current instance.</returns>
+ public int CompareTo( object target )
+ {
+ if ( target is not XDate )
+ throw new ArgumentException();
+
+ return ( this.XLDate ).CompareTo( ((XDate)target).XLDate );
+ }
+
+ #endregion
+
+ #region String Format Conversion Methods
+ // =========================================================================
+ // String Formatting Routines
+ // =========================================================================
+
+ /// <summary>
+ /// Format this XDate value using the default format string (<see cref="DefaultFormatStr"/>).
+ /// </summary>
+ /// <remarks>
+ /// The formatting is done using the <see cref="DateTime"/> <see cref="System.DateTime.ToString(string)"/>
+ /// method in order to provide full localization capability. The DateTime struct is limited to
+ /// dates from 1 AD onward. However, all calendar dates in <see cref="XDate"/> and <see cref="DateTime"/>
+ /// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
+ /// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
+ /// really dates that would have been, had the Gregorian calendar existed. In order to avoid
+ /// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
+ /// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
+ /// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
+ /// </remarks>
+ /// <param name="xlDate">
+ /// The XL date value to be formatted in floating point double format.
+ /// </param>
+ /// <returns>A string representation of the date</returns>
+ public string ToString( double xlDate )
+ {
+ return ToString( xlDate, DefaultFormatStr );
+ }
+
+ /// <summary>
+ /// Format this XDate value using the default format string (see cref="DefaultFormatStr"/>).
+ /// </summary>
+ /// <remarks>
+ /// The formatting is done using the <see cref="DateTime" />
+ /// <see cref="System.DateTime.ToString(String)" />
+ /// method in order to provide full localization capability. The DateTime struct is limited to
+ /// dates from 1 AD onward. However, all calendar dates in <see cref="XDate" /> and
+ /// <see cref="DateTime" />
+ /// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
+ /// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
+ /// really dates that would have been, had the Gregorian calendar existed. In order to avoid
+ /// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
+ /// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
+ /// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
+ /// </remarks>
+ /// <returns>A string representation of the date</returns>
+ public override string ToString()
+ {
+ return ToString( _xlDate, DefaultFormatStr );
+ }
+
+ /// <summary>
+ /// Format this XL Date value using the specified format string. The format
+ /// string is specified according to the <see cref="DateTime"/> class.
+ /// </summary>
+ /// <remarks>
+ /// The formatting is done using the <see cref="DateTime" />
+ /// <see cref="System.DateTime.ToString(String)" />
+ /// method in order to provide full localization capability. The DateTime struct is limited to
+ /// dates from 1 AD onward. However, all calendar dates in <see cref="XDate" /> and
+ /// <see cref="DateTime" />
+ /// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
+ /// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
+ /// really dates that would have been, had the Gregorian calendar existed. In order to avoid
+ /// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
+ /// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
+ /// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
+ /// </remarks>
+ /// <param name="fmtStr">
+ /// The formatting string to be used for the date. See
+ /// <see cref="System.Globalization.DateTimeFormatInfo" />
+ /// class for a list of the format types available.</param>
+ /// <returns>A string representation of the date</returns>
+ public string ToString( string fmtStr )
+ {
+ return ToString( this.XLDate, fmtStr );
+ }
+
+ /// <summary>
+ /// Format the specified XL Date value using the specified format string. The format
+ /// string is specified according to the <see cref="DateTime" /> class.
+ /// </summary>
+ /// <remarks>
+ /// The formatting is done using the <see cref="DateTime" />
+ /// <see cref="System.DateTime.ToString(String)" />
+ /// method in order to provide full localization capability. The DateTime struct is limited to
+ /// dates from 1 AD onward. However, all calendar dates in <see cref="XDate" /> and
+ /// <see cref="DateTime" />
+ /// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
+ /// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
+ /// really dates that would have been, had the Gregorian calendar existed. In order to avoid
+ /// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
+ /// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
+ /// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
+ /// </remarks>
+ /// <param name="xlDate">
+ /// The XL date value to be formatted in floating point double format.
+ /// </param>
+ /// <param name="fmtStr">
+ /// The formatting string to be used for the date. See
+ /// <see cref="System.Globalization.DateTimeFormatInfo" />
+ /// for a list of the format types available.</param>
+ /// <returns>A string representation of the date</returns>
+ public static string ToString( double xlDate, string fmtStr )
+ {
+ int year, month, day, hour, minute, second, millisecond;
+
+ if ( !CheckValidDate( xlDate ) )
+ return "Date Error";
+
+ XLDateToCalendarDate( xlDate, out year, out month, out day, out hour, out minute,
+ out second, out millisecond );
+ if ( year <= 0 )
+ {
+ year = 1 - year;
+ fmtStr = fmtStr + " (BC)";
+ }
+
+ if ( fmtStr.IndexOf("[d]") >= 0 )
+ {
+ fmtStr = fmtStr.Replace( "[d]", ((int) xlDate).ToString() );
+ xlDate -= (int) xlDate;
+ }
+ if ( fmtStr.IndexOf("[h]") >= 0 || fmtStr.IndexOf("[hh]") >= 0 )
+ {
+ fmtStr = fmtStr.Replace( "[h]", ((int) (xlDate * 24)).ToString("d") );
+ fmtStr = fmtStr.Replace( "[hh]", ((int) (xlDate * 24)).ToString("d2") );
+ xlDate = ( xlDate * 24 - (int) (xlDate * 24) ) / 24.0;
+ }
+ if ( fmtStr.IndexOf("[m]") >= 0 || fmtStr.IndexOf("[mm]") >= 0 )
+ {
+ fmtStr = fmtStr.Replace( "[m]", ((int) (xlDate * 1440)).ToString("d") );
+ fmtStr = fmtStr.Replace( "[mm]", ((int) (xlDate * 1440)).ToString("d2") );
+ xlDate = ( xlDate * 1440 - (int) (xlDate * 1440) ) / 1440.0;
+ }
+ if ( fmtStr.IndexOf("[s]") >= 0 || fmtStr.IndexOf("[ss]") >= 0 )
+ {
+ fmtStr = fmtStr.Replace( "[s]", ((int) (xlDate * 86400)).ToString("d") );
+ fmtStr = fmtStr.Replace( "[ss]", ((int) (xlDate * 86400)).ToString("d2") );
+ xlDate = ( xlDate * 86400 - (int) (xlDate * 86400) ) / 86400.0;
+ }
+ if ( fmtStr.IndexOf("[f]") >= 0 )
+ fmtStr = fmtStr.Replace( "[f]", ((int) (xlDate * 864000)).ToString("d") );
+ if ( fmtStr.IndexOf("[ff]") >= 0 )
+ fmtStr = fmtStr.Replace( "[ff]", ((int) (xlDate * 8640000)).ToString("d") );
+ if ( fmtStr.IndexOf("[fff]") >= 0 )
+ fmtStr = fmtStr.Replace( "[fff]", ((int) (xlDate * 86400000)).ToString("d") );
+ if ( fmtStr.IndexOf("[ffff]") >= 0 )
+ fmtStr = fmtStr.Replace( "[ffff]", ((int) (xlDate * 864000000)).ToString("d") );
+ if ( fmtStr.IndexOf("[fffff]") >= 0 )
+ fmtStr = fmtStr.Replace( "[fffff]", ((int) (xlDate * 8640000000)).ToString("d") );
+
+ //DateTime dt = XLDateToDateTime( xlDate );
+ if ( year > 9999 )
+ year = 9999;
+ DateTime dt = new DateTime( year, month, day, hour, minute, second, millisecond );
+ return dt.ToString( fmtStr );
+ }
+
+/*
+ /// <summary>
+ /// Format this XDate value using the specified format string
+ /// </summary>
+ /// <param name="fmtStr">
+ /// The formatting string to be used for the date. The following formatting elements
+ /// will be replaced with the corresponding date values:
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Variable</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item><term>&mmmm</term><description>month name (e.g., January)</description></item>
+ /// <item><term>&mmm</term><description>month abbreviation (e.g., Apr)</description></item>
+ /// <item><term>&mm</term><description>padded month number (e.g. 04)</description></item>
+ /// <item><term>&m</term><description>non-padded month number (e.g., 4)</description></item>
+ /// <item><term>&dd</term><description>padded day number (e.g., 09)</description></item>
+ /// <item><term>&d</term><description>non-padded day number (e.g., 9)</description></item>
+ /// <item><term>&yyyy</term><description>4 digit year number (e.g., 1995)</description></item>
+ /// <item><term>&yy</term><description>two digit year number (e.g., 95)</description></item>
+ /// <item><term>&hh</term><description>padded 24 hour time value (e.g., 08)</description></item>
+ /// <item><term>&h</term><description>non-padded 12 hour time value (e.g., 8)</description></item>
+ /// <item><term>&nn</term><description>padded minute value (e.g, 05)</description></item>
+ /// <item><term>&n</term><description>non-padded minute value (e.g., 5)</description></item>
+ /// <item><term>&ss</term><description>padded second value (e.g., 03)</description></item>
+ /// <item><term>&s</term><description>non-padded second value (e.g., 3)</description></item>
+ /// <item><term>&a</term><description>"am" or "pm"</description></item>
+ /// <item><term>&wwww</term><description>day of week (e.g., Wednesday)</description></item>
+ /// <item><term>&www</term><description>day of week abbreviation (e.g., Wed)</description></item>
+ /// </list>
+ /// </param>
+ /// <example>
+ /// <para>"&wwww, &mmmm &dd, &yyyy &h:&nn &a" ==> "Sunday, February 12, 1956 4:23 pm"</para>
+ /// <para>"&dd-&mmm-&yy" ==> 12-Feb-56</para>
+ /// </example>
+ /// <returns>A string representation of the date</returns>
+ public string ToString( string fmtStr )
+ {
+ return ToString( this.xlDate, fmtStr );
+ }
+
+ /// <summary>
+ /// Format the specified XL Date value using the specified format string
+ /// </summary>
+ /// <param name="xlDate">
+ /// The XL date value to be formatted in floating point double format.
+ /// </param>
+ /// <param name="fmtStr">
+ /// The formatting string to be used for the date. The following formatting elements
+ /// will be replaced with the corresponding date values:
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Variable</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item><term>&mmmm</term><description>month name (e.g., January)</description></item>
+ /// <item><term>&mmm</term><description>month abbreviation (e.g., Apr)</description></item>
+ /// <item><term>&mm</term><description>padded month number (e.g. 04)</description></item>
+ /// <item><term>&m</term><description>non-padded month number (e.g., 4)</description></item>
+ /// <item><term>&dd</term><description>padded day number (e.g., 09)</description></item>
+ /// <item><term>&d</term><description>non-padded day number (e.g., 9)</description></item>
+ /// <item><term>&yyyy</term><description>4 digit year number (e.g., 1995)</description></item>
+ /// <item><term>&yy</term><description>two digit year number (e.g., 95)</description></item>
+ /// <item><term>&hh</term><description>padded 24 hour time value (e.g., 08)</description></item>
+ /// <item><term>&h</term><description>non-padded 12 hour time value (e.g., 8)</description></item>
+ /// <item><term>&nn</term><description>padded minute value (e.g, 05)</description></item>
+ /// <item><term>&n</term><description>non-padded minute value (e.g., 5)</description></item>
+ /// <item><term>&ss</term><description>padded second value (e.g., 03)</description></item>
+ /// <item><term>&s</term><description>non-padded second value (e.g., 3)</description></item>
+ /// <item><term>&a</term><description>"am" or "pm"</description></item>
+ /// <item><term>&wwww</term><description>day of week (e.g., Wednesday)</description></item>
+ /// <item><term>&www</term><description>day of week abbreviation (e.g., Wed)</description></item>
+ /// </list>
+ /// </param>
+ /// <example>
+ /// <para>"&wwww, &mmmm &dd, &yyyy &h:&nn &a" ==> "Sunday, February 12, 1956 4:23 pm"</para>
+ /// <para>"&dd-&mmm-&yy" ==> 12-Feb-56</para>
+ /// </example>
+ /// <returns>A string representation of the date</returns>
+ public static string ToString( double xlDate, string fmtStr )
+ {
+ string[] longMonth = { "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December" };
+ string[] shortMonth = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ string[] longDoW = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday" };
+ string[] shortDoW = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+
+ int year, month, day, hour, minute, second;
+ XLDateToCalendarDate( xlDate, out year, out month, out day, out hour, out minute, out second );
+
+ string resultStr = fmtStr.Replace( "&mmmm", longMonth[ month - 1 ] );
+ resultStr = resultStr.Replace( "&mmm", shortMonth[ month - 1 ] );
+ resultStr = resultStr.Replace( "&mm", month.ToString( "d2" ) );
+ resultStr = resultStr.Replace( "&m", month.ToString( "d" ) );
+ resultStr = resultStr.Replace( "&yyyy", year.ToString( "d" ) );
+ resultStr = resultStr.Replace( "&yy", (year%100).ToString( "d2" ) );
+ resultStr = resultStr.Replace( "&dd", day.ToString( "d2" ) );
+ resultStr = resultStr.Replace( "&d", day.ToString( "d" ) );
+ resultStr = resultStr.Replace( "&hh", hour.ToString( "d2" ) );
+ resultStr = resultStr.Replace( "&h", (((hour+11)%12)+1).ToString( "d" ) );
+ resultStr = resultStr.Replace( "&nn", minute.ToString( "d2" ) );
+ resultStr = resultStr.Replace( "&n", minute.ToString( "d" ) );
+ resultStr = resultStr.Replace( "&ss", second.ToString( "d2" ) );
+ resultStr = resultStr.Replace( "&s", second.ToString( "d" ) );
+ resultStr = resultStr.Replace( "&a", (hour>=12) ? "pm" : "am" );
+ resultStr = resultStr.Replace( "&wwww", longDoW[ XLDateToDayOfWeek( xlDate ) ] );
+ resultStr = resultStr.Replace( "&www", shortDoW[ XLDateToDayOfWeek( xlDate ) ] );
+
+
+ return resultStr;
+ }
+*/
+
+ #endregion
+ }
+}
diff --git a/ZedGraph/Y2Axis.cs b/ZedGraph/Y2Axis.cs
new file mode 100644
index 0000000..a32b3b5
--- /dev/null
+++ b/ZedGraph/Y2Axis.cs
@@ -0,0 +1,254 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// <see cref="Y2Axis"/> inherits from <see cref="Axis"/>, and defines the
+ /// special characteristics of a vertical axis, specifically located on
+ /// the right side of the <see cref="Chart.Rect"/> of the <see cref="GraphPane"/>
+ /// object
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.16 $ $Date: 2007-04-16 00:03:05 $ </version>
+ [Serializable]
+ public class Y2Axis : Axis, ICloneable, ISerializable
+ {
+ #region Defaults
+ /// <summary>
+ /// A simple subclass of the <see cref="Default"/> class that defines the
+ /// default property values for the <see cref="Y2Axis"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ // Default Y2 Axis properties
+ /// <summary>
+ /// The default display mode for the <see cref="Y2Axis"/>
+ /// (<see cref="Axis.IsVisible"/> property). true to display the scale
+ /// values, title, tic marks, false to hide the axis entirely.
+ /// </summary>
+ public static bool IsVisible = false;
+ /// <summary>
+ /// Determines if a line will be drawn at the zero value for the
+ /// <see cref="Y2Axis"/>, that is, a line that
+ /// divides the negative values from positive values.
+ /// <seealso cref="MajorGrid.IsZeroLine"/>.
+ /// </summary>
+ public static bool IsZeroLine = true;
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="Y2Axis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class
+ /// </summary>
+ public Y2Axis()
+ : this( "Y2 Axis" )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="Y2Axis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class, except
+ /// for the axis title
+ /// </summary>
+ /// <param name="title">The <see cref="Axis.Title"/> for this axis</param>
+ public Y2Axis( string title )
+ : base( title )
+ {
+ _isVisible = Default.IsVisible;
+ _majorGrid._isZeroLine = Default.IsZeroLine;
+ _scale._fontSpec.Angle = -90.0F;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The Y2Axis object from which to copy</param>
+ public Y2Axis( Y2Axis rhs )
+ : base( rhs )
+ {
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Y2Axis Clone()
+ {
+ return new Y2Axis( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected Y2Axis( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Setup the Transform Matrix to handle drawing of this <see cref="Y2Axis"/>
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void SetTransformMatrix( Graphics g, GraphPane pane, float scaleFactor )
+ {
+ // Move the origin to the BottomRight of the ChartRect, which is the left
+ // side of the Y2 axis (facing from the label side)
+ g.TranslateTransform( pane.Chart._rect.Right, pane.Chart._rect.Bottom );
+ // rotate so this axis is in the left-right direction
+ g.RotateTransform( -90 );
+ }
+
+ /// <summary>
+ /// Determines if this <see cref="Axis" /> object is a "primary" one.
+ /// </summary>
+ /// <remarks>
+ /// The primary axes are the <see cref="XAxis" /> (always), the first
+ /// <see cref="YAxis" /> in the <see cref="GraphPane.YAxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0), and the first
+ /// <see cref="Y2Axis" /> in the <see cref="GraphPane.Y2AxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0). Note that
+ /// <see cref="GraphPane.YAxis" /> and <see cref="GraphPane.Y2Axis" />
+ /// always reference the primary axes.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>true for a primary <see cref="Axis" />, false otherwise</returns>
+ override internal bool IsPrimary( GraphPane pane )
+ {
+ return this == pane.Y2Axis;
+ }
+
+ /// <summary>
+ /// Calculate the "shift" size, in pixels, in order to shift the axis from its default
+ /// location to the value specified by <see cref="Axis.Cross"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>The shift amount measured in pixels</returns>
+ internal override float CalcCrossShift( GraphPane pane )
+ {
+ double effCross = EffectiveCrossValue( pane );
+
+ if ( !_crossAuto )
+ return pane.XAxis.Scale.Transform( effCross ) - pane.XAxis.Scale._maxPix;
+ else
+ return 0;
+ }
+ /*
+ override internal bool IsCrossed( GraphPane pane )
+ {
+ return !this.crossAuto && this.cross > pane.XAxis.Min && this.cross < pane.XAxis.Max;
+ }
+ */
+ /// <summary>
+ /// Gets the "Cross" axis that corresponds to this axis.
+ /// </summary>
+ /// <remarks>
+ /// The cross axis is the axis which determines the of this Axis when the
+ /// <see cref="Axis.Cross" >Axis.Cross</see> property is used. The
+ /// cross axis for any <see cref="XAxis" /> or <see cref="X2Axis" />
+ /// is always the primary <see cref="YAxis" />, and
+ /// the cross axis for any <see cref="YAxis" /> or <see cref="Y2Axis" /> is
+ /// always the primary <see cref="XAxis" />.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ override public Axis GetCrossAxis( GraphPane pane )
+ {
+ return pane.XAxis;
+ }
+
+// override internal float GetMinPix( GraphPane pane )
+// {
+// return pane.Chart._rect.Top;
+// }
+
+ #endregion
+
+ }
+}
+
diff --git a/ZedGraph/Y2AxisList.cs b/ZedGraph/Y2AxisList.cs
new file mode 100644
index 0000000..65d07ae
--- /dev/null
+++ b/ZedGraph/Y2AxisList.cs
@@ -0,0 +1,188 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="YAxis"/> objects.
+ /// </summary>
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.3 $ $Date: 2006-06-24 20:26:43 $ </version>
+ [Serializable]
+ public class Y2AxisList : List<Y2Axis>, ICloneable
+ {
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the collection class.
+ /// </summary>
+ public Y2AxisList()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="Y2AxisList"/> object from which to copy</param>
+ public Y2AxisList( Y2AxisList rhs )
+ {
+ foreach ( Y2Axis item in rhs )
+ {
+ this.Add( item.Clone() );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public Y2AxisList Clone()
+ {
+ return new Y2AxisList( this );
+ }
+
+ #endregion
+
+ #region List Methods
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="Axis"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="YAxis"/> object to be accessed.</param>
+ /// <value>An <see cref="Axis"/> object reference.</value>
+ public new Y2Axis this[int index]
+ {
+ get { return ( ( ( index < 0 || index >= this.Count ) ? null : base[index] ) ); }
+ }
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="Axis"/> object by
+ /// its <see cref="Axis.Title"/> string.
+ /// </summary>
+ /// <param name="title">The string title of the
+ /// <see cref="YAxis"/> object to be accessed.</param>
+ /// <value>A <see cref="Axis"/> object reference.</value>
+ public Y2Axis this[string title]
+ {
+ get
+ {
+ int index = IndexOf( title );
+ if ( index >= 0 )
+ return this[index];
+ else
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="Axis"/> with the specified <see cref="Axis.Title"/>.
+ /// </summary>
+ /// <remarks>The comparison of titles is not case sensitive, but it must include
+ /// all characters including punctuation, spaces, etc.</remarks>
+ /// <param name="title">The <see cref="String"/> label that is in the
+ /// <see cref="Axis.Title"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="Axis"/>,
+ /// or -1 if the <see cref="Axis.Title"/> was not found in the list</returns>
+ /// <seealso cref="IndexOfTag"/>
+ public int IndexOf( string title )
+ {
+ int index = 0;
+ foreach ( Y2Axis axis in this )
+ {
+ if ( String.Compare( axis.Title._text, title, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="Axis"/> with the specified <see cref="Axis.Tag" />.
+ /// </summary>
+ /// <remarks>In order for this method to work, the <see cref="Axis.Tag" />
+ /// property must be of type <see cref="String"/>.</remarks>
+ /// <param name="tagStr">The <see cref="String"/> tag that is in the
+ /// <see cref="Axis.Tag" /> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="Axis" />,
+ /// or -1 if the <see cref="Axis.Tag" /> string is not in the list</returns>
+ /// <seealso cref="IndexOf" />
+ public int IndexOfTag( string tagStr )
+ {
+ int index = 0;
+ foreach ( Y2Axis axis in this )
+ {
+ if ( axis.Tag is string &&
+ String.Compare( (string)axis.Tag, tagStr, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Create a new <see cref="Y2Axis" /> and add it to this list.
+ /// </summary>
+ /// <param name="title">The title string for the new axis</param>
+ /// <returns>An integer representing the ordinal position of the new <see cref="Y2Axis" /> in
+ /// this <see cref="Y2AxisList" />. This is the value that you would set the
+ /// <see cref="CurveItem.YAxisIndex" /> property of a given <see cref="CurveItem" /> to
+ /// assign it to this new <see cref="Y2Axis" />. Note that, for a <see cref="Y2Axis" />,
+ /// you would also need to set the <see cref="CurveItem.IsY2Axis" /> property to true.</returns>
+ public int Add( string title )
+ {
+ Y2Axis axis = new Y2Axis( title );
+ Add( axis );
+
+ return Count - 1;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/YAxis.cs b/ZedGraph/YAxis.cs
new file mode 100644
index 0000000..200e9c8
--- /dev/null
+++ b/ZedGraph/YAxis.cs
@@ -0,0 +1,254 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// <see cref="YAxis"/> inherits from <see cref="Axis"/>, and defines the
+ /// special characteristics of a vertical axis, specifically located on
+ /// the right side of the <see cref="Chart.Rect"/> of the <see cref="GraphPane"/>
+ /// object
+ /// </summary>
+ ///
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.16 $ $Date: 2007-04-16 00:03:06 $ </version>
+ [Serializable]
+ public class YAxis : Axis, ICloneable, ISerializable
+ {
+ #region Defaults
+ /// <summary>
+ /// A simple struct that defines the
+ /// default property values for the <see cref="YAxis"/> class.
+ /// </summary>
+ public new struct Default
+ {
+ // Default Y Axis properties
+ /// <summary>
+ /// The default display mode for the <see cref="YAxis"/>
+ /// (<see cref="Axis.IsVisible"/> property). true to display the scale
+ /// values, title, tic marks, false to hide the axis entirely.
+ /// </summary>
+ public static bool IsVisible = true;
+ /// <summary>
+ /// Determines if a line will be drawn at the zero value for the
+ /// <see cref="YAxis"/>, that is, a line that
+ /// divides the negative values from positive values.
+ /// <seealso cref="MajorGrid.IsZeroLine"/>.
+ /// </summary>
+ public static bool IsZeroLine = true;
+ }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="YAxis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class
+ /// </summary>
+ public YAxis()
+ : this( "Y Axis" )
+ {
+ }
+
+ /// <summary>
+ /// Default constructor that sets all <see cref="YAxis"/> properties to
+ /// default values as defined in the <see cref="Default"/> class, except
+ /// for the axis title
+ /// </summary>
+ /// <param name="title">The <see cref="Axis.Title"/> for this axis</param>
+ public YAxis( string title )
+ : base( title )
+ {
+ _isVisible = Default.IsVisible;
+ _majorGrid._isZeroLine = Default.IsZeroLine;
+ _scale._fontSpec.Angle = 90.0F;
+ _title._fontSpec.Angle = -180F;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The YAxis object from which to copy</param>
+ public YAxis( YAxis rhs )
+ : base( rhs )
+ {
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public YAxis Clone()
+ {
+ return new YAxis( this );
+ }
+
+ #endregion
+
+ #region Serialization
+ /// <summary>
+ /// Current schema value that defines the version of the serialized file
+ /// </summary>
+ public const int schema2 = 10;
+
+ /// <summary>
+ /// Constructor for deserializing objects
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
+ /// </param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
+ /// </param>
+ protected YAxis( SerializationInfo info, StreamingContext context )
+ : base( info, context )
+ {
+ // The schema value is just a file version parameter. You can use it to make future versions
+ // backwards compatible as new member variables are added to classes
+ int sch = info.GetInt32( "schema2" );
+
+ }
+ /// <summary>
+ /// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
+ /// </summary>
+ /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
+ /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
+ public override void GetObjectData( SerializationInfo info, StreamingContext context )
+ {
+ base.GetObjectData( info, context );
+ info.AddValue( "schema2", schema2 );
+ }
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Setup the Transform Matrix to handle drawing of this <see cref="YAxis"/>
+ /// </summary>
+ /// <param name="g">
+ /// A graphic device object to be drawn into. This is normally e.Graphics from the
+ /// PaintEventArgs argument to the Paint() method.
+ /// </param>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <param name="scaleFactor">
+ /// The scaling factor to be used for rendering objects. This is calculated and
+ /// passed down by the parent <see cref="GraphPane"/> object using the
+ /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
+ /// font sizes, etc. according to the actual size of the graph.
+ /// </param>
+ override public void SetTransformMatrix( Graphics g, GraphPane pane, float scaleFactor )
+ {
+ // Move the origin to the TopLeft of the ChartRect, which is the left
+ // side of the axis (facing from the label side)
+ g.TranslateTransform( pane.Chart._rect.Left, pane.Chart._rect.Top );
+ // rotate so this axis is in the left-right direction
+ g.RotateTransform( 90 );
+ }
+
+ /// <summary>
+ /// Determines if this <see cref="Axis" /> object is a "primary" one.
+ /// </summary>
+ /// <remarks>
+ /// The primary axes are the <see cref="XAxis" /> (always), the first
+ /// <see cref="YAxis" /> in the <see cref="GraphPane.YAxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0), and the first
+ /// <see cref="Y2Axis" /> in the <see cref="GraphPane.Y2AxisList" />
+ /// (<see cref="CurveItem.YAxisIndex" /> = 0). Note that
+ /// <see cref="GraphPane.YAxis" /> and <see cref="GraphPane.Y2Axis" />
+ /// always reference the primary axes.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>true for a primary <see cref="Axis" />, false otherwise</returns>
+ override internal bool IsPrimary( GraphPane pane )
+ {
+ return this == pane.YAxis;
+ }
+
+ /// <summary>
+ /// Calculate the "shift" size, in pixels, in order to shift the axis from its default
+ /// location to the value specified by <see cref="Axis.Cross"/>.
+ /// </summary>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ /// <returns>The shift amount measured in pixels</returns>
+ internal override float CalcCrossShift( GraphPane pane )
+ {
+ double effCross = EffectiveCrossValue( pane );
+
+ if ( !_crossAuto )
+ return pane.XAxis.Scale._minPix - pane.XAxis.Scale.Transform( effCross );
+ else
+ return 0;
+ }
+ /*
+ override internal bool IsCrossed( GraphPane pane )
+ {
+ return !this.crossAuto && this.cross > pane.XAxis.Min && this.cross < pane.XAxis.Max;
+ }
+ */
+ /// <summary>
+ /// Gets the "Cross" axis that corresponds to this axis.
+ /// </summary>
+ /// <remarks>
+ /// The cross axis is the axis which determines the of this Axis when the
+ /// <see cref="Axis.Cross" >Axis.Cross</see> property is used. The
+ /// cross axis for any <see cref="XAxis" /> or <see cref="X2Axis" />
+ /// is always the primary <see cref="YAxis" />, and
+ /// the cross axis for any <see cref="YAxis" /> or <see cref="Y2Axis" /> is
+ /// always the primary <see cref="XAxis" />.
+ /// </remarks>
+ /// <param name="pane">
+ /// A reference to the <see cref="GraphPane"/> object that is the parent or
+ /// owner of this object.
+ /// </param>
+ override public Axis GetCrossAxis( GraphPane pane )
+ {
+ return pane.XAxis;
+ }
+
+ // override internal float GetMinPix( GraphPane pane )
+ // {
+ // return pane.Chart._rect.Top;
+ // }
+
+
+ #endregion
+ }
+}
+
diff --git a/ZedGraph/YAxisList.cs b/ZedGraph/YAxisList.cs
new file mode 100644
index 0000000..bd431d2
--- /dev/null
+++ b/ZedGraph/YAxisList.cs
@@ -0,0 +1,187 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2005 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A collection class containing a list of <see cref="YAxis"/> objects.
+ /// </summary>
+ ///
+ /// <author>John Champion</author>
+ /// <version> $Revision: 3.3 $ $Date: 2006-06-24 20:26:43 $ </version>
+ [Serializable]
+ public class YAxisList : List<YAxis>, ICloneable
+ {
+
+ #region Constructors
+
+ /// <summary>
+ /// Default constructor for the collection class.
+ /// </summary>
+ public YAxisList()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="YAxisList"/> object from which to copy</param>
+ public YAxisList( YAxisList rhs )
+ {
+ foreach ( YAxis item in rhs )
+ {
+ this.Add( item.Clone() );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public YAxisList Clone()
+ {
+ return new YAxisList( this );
+ }
+
+ #endregion
+
+ #region List Methods
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="Axis"/> object by
+ /// its ordinal position in the list.
+ /// </summary>
+ /// <param name="index">The ordinal position (zero-based) of the
+ /// <see cref="YAxis"/> object to be accessed.</param>
+ /// <value>An <see cref="Axis"/> object reference.</value>
+ public new YAxis this[int index]
+ {
+ get { return ( ( ( index < 0 || index >= this.Count ) ? null : base[index] ) ); }
+ }
+
+ /// <summary>
+ /// Indexer to access the specified <see cref="Axis"/> object by
+ /// its <see cref="Axis.Title"/> string.
+ /// </summary>
+ /// <param name="title">The string title of the
+ /// <see cref="YAxis"/> object to be accessed.</param>
+ /// <value>A <see cref="Axis"/> object reference.</value>
+ public YAxis this[string title]
+ {
+ get
+ {
+ int index = IndexOf( title );
+ if ( index >= 0 )
+ return this[index];
+ else
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="Axis"/> with the specified <see cref="Axis.Title"/>.
+ /// </summary>
+ /// <remarks>The comparison of titles is not case sensitive, but it must include
+ /// all characters including punctuation, spaces, etc.</remarks>
+ /// <param name="title">The <see cref="String"/> label that is in the
+ /// <see cref="Axis.Title"/> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="Axis"/>,
+ /// or -1 if the <see cref="Axis.Title"/> was not found in the list</returns>
+ /// <seealso cref="IndexOfTag"/>
+ public int IndexOf( string title )
+ {
+ int index = 0;
+ foreach ( YAxis axis in this )
+ {
+ if ( String.Compare( axis.Title._text, title, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Return the zero-based position index of the
+ /// <see cref="Axis"/> with the specified <see cref="Axis.Tag" />.
+ /// </summary>
+ /// <remarks>In order for this method to work, the <see cref="Axis.Tag" />
+ /// property must be of type <see cref="String"/>.
+ /// </remarks>
+ /// <param name="tagStr">The <see cref="String"/> tag that is in the
+ /// <see cref="Axis.Tag" /> attribute of the item to be found.
+ /// </param>
+ /// <returns>The zero-based index of the specified <see cref="Axis" />,
+ /// or -1 if the <see cref="Axis.Tag" /> string is not in the list</returns>
+ public int IndexOfTag( string tagStr )
+ {
+ int index = 0;
+ foreach ( YAxis axis in this )
+ {
+ if ( axis.Tag is string &&
+ String.Compare( (string)axis.Tag, tagStr, true ) == 0 )
+ return index;
+ index++;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Create a new <see cref="YAxis" /> and add it to this list.
+ /// </summary>
+ /// <param name="title">The title string for the new axis</param>
+ /// <returns>An integer representing the ordinal position of the new <see cref="YAxis" /> in
+ /// this <see cref="YAxisList" />. This is the value that you would set the
+ /// <see cref="CurveItem.YAxisIndex" /> property of a given <see cref="CurveItem" /> to
+ /// assign it to this new <see cref="YAxis" />.</returns>
+ public int Add( string title )
+ {
+ YAxis axis = new YAxis( title );
+ Add( axis );
+
+ return Count - 1;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ZedGraph.csproj b/ZedGraph/ZedGraph.csproj
new file mode 100644
index 0000000..79d9c0d
--- /dev/null
+++ b/ZedGraph/ZedGraph.csproj
@@ -0,0 +1,61 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B99650EE-AF46-47B4-A4A9-212ADE7809B7}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ZedGraph</RootNamespace>
+ <AssemblyName>ZedGraph</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Class1.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ZedGraph\ZedGraphControl.cs">
+ <SubType>UserControl</SubType>
+ </Compile>
+ <Compile Include="ZedGraph\ZedGraphControl.Designer.cs">
+ <DependentUpon>ZedGraphControl.cs</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="ZedGraph\ZedGraphControl.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>ZedGraphControl.cs</DependentUpon>
+ </EmbeddedResource>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
diff --git a/ZedGraph/ZedGraphControl.ContextMenu.cs b/ZedGraph/ZedGraphControl.ContextMenu.cs
new file mode 100644
index 0000000..8658efe
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.ContextMenu.cs
@@ -0,0 +1,892 @@
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Windows.Forms;
+using System.Threading;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Text;
+
+using System.Runtime.InteropServices;
+//using System.Diagnostics;
+
+namespace ZedGraph
+{
+ partial class ZedGraphControl
+ {
+
+ #region ContextMenu
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Public enumeration that specifies the type of
+ /// object present at the Context Menu's mouse location
+ /// </summary>
+ public enum ContextMenuObjectState
+ {
+ /// <summary>
+ /// The object is an Inactive Curve Item at the Context Menu's mouse position
+ /// </summary>
+ InactiveSelection,
+ /// <summary>
+ /// The object is an active Curve Item at the Context Menu's mouse position
+ /// </summary>
+ ActiveSelection,
+ /// <summary>
+ /// There is no selectable object present at the Context Menu's mouse position
+ /// </summary>
+ Background
+ }
+
+ //Revision: JCarpenter 10/06
+ /// <summary>
+ /// Find the object currently under the mouse cursor, and return its state.
+ /// </summary>
+ private ContextMenuObjectState GetObjectState()
+ {
+ ContextMenuObjectState objState = ContextMenuObjectState.Background;
+
+ // Determine object state
+ Point mousePt = this.PointToClient( Control.MousePosition );
+ int iPt;
+ GraphPane pane;
+ object nearestObj;
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ if ( this.MasterPane.FindNearestPaneObject( mousePt, g, out pane,
+ out nearestObj, out iPt ) )
+ {
+ CurveItem item = nearestObj as CurveItem;
+
+ if ( item != null && iPt >= 0 )
+ {
+ if ( item.IsSelected )
+ objState = ContextMenuObjectState.ActiveSelection;
+ else
+ objState = ContextMenuObjectState.InactiveSelection;
+ }
+ }
+ }
+
+ return objState;
+ }
+
+ /// <summary>
+ /// protected method to handle the popup context menu in the <see cref="ZedGraphControl"/>.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void contextMenuStrip1_Opening( object sender, CancelEventArgs e )
+ {
+ // disable context menu by default
+ e.Cancel = true;
+ ContextMenuStrip menuStrip = sender as ContextMenuStrip;
+
+ //Revision: JCarpenter 10/06
+ ContextMenuObjectState objState = GetObjectState();
+
+ if ( _masterPane != null && menuStrip != null )
+ {
+ menuStrip.Items.Clear();
+
+ _isZooming = false;
+ _isPanning = false;
+ Cursor.Current = Cursors.Default;
+
+ _menuClickPt = this.PointToClient( Control.MousePosition );
+ GraphPane pane = _masterPane.FindPane( _menuClickPt );
+
+ if ( _isShowContextMenu )
+ {
+ string menuStr = string.Empty;
+
+ ToolStripMenuItem item = new ToolStripMenuItem();
+ item.Name = "copy";
+ item.Tag = "copy";
+ item.Text = _resourceManager.GetString( "copy" );
+ item.Click += new System.EventHandler( this.MenuClick_Copy );
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "save_as";
+ item.Tag = "save_as";
+ item.Text = _resourceManager.GetString( "save_as" );
+ item.Click += new System.EventHandler( this.MenuClick_SaveAs );
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "page_setup";
+ item.Tag = "page_setup";
+ item.Text = _resourceManager.GetString( "page_setup" );
+ item.Click += new System.EventHandler( this.MenuClick_PageSetup );
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "print";
+ item.Tag = "print";
+ item.Text = _resourceManager.GetString( "print" );
+ item.Click += new System.EventHandler( this.MenuClick_Print );
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "show_val";
+ item.Tag = "show_val";
+ item.Text = _resourceManager.GetString( "show_val" );
+ item.Click += new System.EventHandler( this.MenuClick_ShowValues );
+ item.Checked = this.IsShowPointValues;
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "unzoom";
+ item.Tag = "unzoom";
+
+ if ( pane == null || pane.ZoomStack.IsEmpty )
+ menuStr = _resourceManager.GetString( "unzoom" );
+ else
+ {
+ switch ( pane.ZoomStack.Top.Type )
+ {
+ case ZoomState.StateType.Zoom:
+ case ZoomState.StateType.WheelZoom:
+ menuStr = _resourceManager.GetString( "unzoom" );
+ break;
+ case ZoomState.StateType.Pan:
+ menuStr = _resourceManager.GetString( "unpan" );
+ break;
+ case ZoomState.StateType.Scroll:
+ menuStr = _resourceManager.GetString( "unscroll" );
+ break;
+ }
+ }
+
+ //menuItem.Text = "Un-" + ( ( pane == null || pane.zoomStack.IsEmpty ) ?
+ // "Zoom" : pane.zoomStack.Top.TypeString );
+ item.Text = menuStr;
+ item.Click += new EventHandler( this.MenuClick_ZoomOut );
+ if ( pane == null || pane.ZoomStack.IsEmpty )
+ item.Enabled = false;
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "undo_all";
+ item.Tag = "undo_all";
+ menuStr = _resourceManager.GetString( "undo_all" );
+ item.Text = menuStr;
+ item.Click += new EventHandler( this.MenuClick_ZoomOutAll );
+ if ( pane == null || pane.ZoomStack.IsEmpty )
+ item.Enabled = false;
+ menuStrip.Items.Add( item );
+
+ item = new ToolStripMenuItem();
+ item.Name = "set_default";
+ item.Tag = "set_default";
+ menuStr = _resourceManager.GetString( "set_default" );
+ item.Text = menuStr;
+ item.Click += new EventHandler( this.MenuClick_RestoreScale );
+ if ( pane == null )
+ item.Enabled = false;
+ menuStrip.Items.Add( item );
+
+ // if e.Cancel is set to false, the context menu does not display
+ // it is initially set to false because the context menu has no items
+ e.Cancel = false;
+
+ // Provide Callback for User to edit the context menu
+ //Revision: JCarpenter 10/06 - add ContextMenuObjectState objState
+ if ( this.ContextMenuBuilder != null )
+ this.ContextMenuBuilder( this, menuStrip, _menuClickPt, objState );
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Copy" context menu item. Copies the current image to a bitmap on the
+ /// clipboard.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_Copy( System.Object sender, System.EventArgs e )
+ {
+ Copy( _isShowCopyMessage );
+ }
+
+ /// <summary>
+ /// Handler for the "Copy" context menu item. Copies the current image to a bitmap on the
+ /// clipboard.
+ /// </summary>
+ /// <param name="isShowMessage">boolean value that determines whether or not a prompt will be
+ /// displayed. true to show a message of "Image Copied to ClipBoard".</param>
+ public void Copy( bool isShowMessage )
+ {
+ if ( _masterPane != null )
+ {
+ //Clipboard.SetDataObject( _masterPane.GetImage(), true );
+
+ // Threaded copy mode to avoid crash with MTA
+ // Contributed by Dave Moor
+ Thread ct = new Thread( new ThreadStart( this.ClipboardCopyThread ) );
+ //ct.ApartmentState = ApartmentState.STA;
+ ct.SetApartmentState( ApartmentState.STA );
+ ct.Start();
+ ct.Join();
+
+ if ( isShowMessage )
+ {
+ string str = _resourceManager.GetString( "copied_to_clip" );
+ //MessageBox.Show( "Image Copied to ClipBoard" );
+ MessageBox.Show( str );
+ }
+ }
+ }
+
+ /// <summary>
+ /// A threaded version of the copy method to avoid crash with MTA
+ /// </summary>
+ private void ClipboardCopyThread()
+ {
+ Clipboard.SetDataObject( ImageRender(), true );
+ }
+
+ //
+ /// <summary>
+ /// Setup for creation of a new image, applying appropriate anti-alias properties and
+ /// returning the resultant image file
+ /// </summary>
+ /// <returns></returns>
+ private Image ImageRender()
+ {
+ return _masterPane.GetImage( _masterPane.IsAntiAlias );
+ }
+
+ /// <summary>
+ /// Special handler that copies the current image to an Emf file on the clipboard.
+ /// </summary>
+ /// <remarks>This version is similar to the regular <see cref="Copy" /> method, except that
+ /// it will place an Emf image (vector) on the ClipBoard instead of the regular bitmap.</remarks>
+ /// <param name="isShowMessage">boolean value that determines whether or not a prompt will be
+ /// displayed. true to show a message of "Image Copied to ClipBoard".</param>
+ public void CopyEmf(bool isShowMessage)
+ {
+ if (_masterPane != null)
+ {
+ // Threaded copy mode to avoid crash with MTA
+ // Contributed by Dave Moor
+ Thread ct = new Thread(new ThreadStart(this.ClipboardCopyThreadEmf));
+ //ct.ApartmentState = ApartmentState.STA;
+ ct.SetApartmentState(ApartmentState.STA);
+ ct.Start();
+ ct.Join();
+
+ if (isShowMessage)
+ {
+ string str = _resourceManager.GetString("copied_to_clip");
+ MessageBox.Show(str);
+ }
+ }
+ }
+
+ /// <summary>
+ /// A threaded version of the copy method to avoid crash with MTA
+ /// </summary>
+ private void ClipboardCopyThreadEmf()
+ {
+ using (Graphics g = this.CreateGraphics())
+ {
+ IntPtr hdc = g.GetHdc();
+ Metafile metaFile = new Metafile(hdc, EmfType.EmfPlusOnly);
+ g.ReleaseHdc(hdc);
+
+ using (Graphics gMeta = Graphics.FromImage(metaFile))
+ {
+ this._masterPane.Draw( gMeta );
+ }
+
+ //IntPtr hMeta = metaFile.GetHenhmetafile();
+ ClipboardMetafileHelper.PutEnhMetafileOnClipboard( this.Handle, metaFile );
+ //System.Windows.Forms.Clipboard.SetDataObject(hMeta, true);
+
+ //g.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Save Image As" context menu item. Copies the current image to the selected
+ /// file.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_SaveAs( System.Object sender, System.EventArgs e )
+ {
+ SaveAs();
+ }
+
+ /// <summary>
+ /// Handler for the "Save Image As" context menu item. Copies the current image to the selected
+ /// file in either the Emf (vector), or a variety of Bitmap formats.
+ /// </summary>
+ /// <remarks>
+ /// Note that <see cref="SaveAsBitmap" /> and <see cref="SaveAsEmf" /> methods are provided
+ /// which allow for Bitmap-only or Emf-only handling of the "Save As" context menu item.
+ /// </remarks>
+ public void SaveAs()
+ {
+ SaveAs( null );
+ }
+
+ /// <summary>
+ /// Copies the current image to the selected file in
+ /// Emf (vector), or a variety of Bitmap formats.
+ /// </summary>
+ /// <param name="DefaultFileName">
+ /// Accepts a default file name for the file dialog (if "" or null, default is not used)
+ /// </param>
+ /// <returns>
+ /// The file name saved, or "" if cancelled.
+ /// </returns>
+ /// <remarks>
+ /// Note that <see cref="SaveAsBitmap" /> and <see cref="SaveAsEmf" /> methods are provided
+ /// which allow for Bitmap-only or Emf-only handling of the "Save As" context menu item.
+ /// </remarks>
+ public String SaveAs( String DefaultFileName )
+ {
+ if ( _masterPane != null )
+ {
+ _saveFileDialog.Filter =
+ "Emf Format (*.emf)|*.emf|" +
+ "PNG Format (*.png)|*.png|" +
+ "Gif Format (*.gif)|*.gif|" +
+ "Jpeg Format (*.jpg)|*.jpg|" +
+ "Tiff Format (*.tif)|*.tif|" +
+ "Bmp Format (*.bmp)|*.bmp";
+
+ if ( DefaultFileName != null && DefaultFileName.Length > 0 )
+ {
+ String ext = System.IO.Path.GetExtension( DefaultFileName ).ToLower();
+ switch (ext)
+ {
+ case ".emf": _saveFileDialog.FilterIndex = 1; break;
+ case ".png": _saveFileDialog.FilterIndex = 2; break;
+ case ".gif": _saveFileDialog.FilterIndex = 3; break;
+ case ".jpeg":
+ case ".jpg": _saveFileDialog.FilterIndex = 4; break;
+ case ".tiff":
+ case ".tif": _saveFileDialog.FilterIndex = 5; break;
+ case ".bmp": _saveFileDialog.FilterIndex = 6; break;
+ }
+ //If we were passed a file name, not just an extension, use it
+ if ( DefaultFileName.Length > ext.Length )
+ {
+ _saveFileDialog.FileName = DefaultFileName;
+ }
+ }
+
+ if ( _saveFileDialog.ShowDialog() == DialogResult.OK )
+ {
+ Stream myStream = _saveFileDialog.OpenFile();
+ if ( myStream != null )
+ {
+ if ( _saveFileDialog.FilterIndex == 1 )
+ {
+ myStream.Close();
+ SaveEmfFile( _saveFileDialog.FileName );
+ }
+ else
+ {
+ ImageFormat format = ImageFormat.Png;
+ switch (_saveFileDialog.FilterIndex)
+ {
+ case 2: format = ImageFormat.Png; break;
+ case 3: format = ImageFormat.Gif; break;
+ case 4: format = ImageFormat.Jpeg; break;
+ case 5: format = ImageFormat.Tiff; break;
+ case 6: format = ImageFormat.Bmp; break;
+ }
+
+ ImageRender().Save( myStream, format );
+ //_masterPane.GetImage().Save( myStream, format );
+ myStream.Close();
+ }
+ return _saveFileDialog.FileName;
+ }
+ }
+ }
+ return "";
+ }
+
+ /// <summary>
+ /// Handler for the "Save Image As" context menu item. Copies the current image to the selected
+ /// Bitmap file.
+ /// </summary>
+ /// <remarks>
+ /// Note that this handler saves as a bitmap only. The default handler is
+ /// <see cref="SaveAs()" />, which allows for Bitmap or EMF formats
+ /// </remarks>
+ public void SaveAsBitmap()
+ {
+ if ( _masterPane != null )
+ {
+ _saveFileDialog.Filter =
+ "PNG Format (*.png)|*.png|" +
+ "Gif Format (*.gif)|*.gif|" +
+ "Jpeg Format (*.jpg)|*.jpg|" +
+ "Tiff Format (*.tif)|*.tif|" +
+ "Bmp Format (*.bmp)|*.bmp";
+
+ if ( _saveFileDialog.ShowDialog() == DialogResult.OK )
+ {
+ ImageFormat format = ImageFormat.Png;
+ if ( _saveFileDialog.FilterIndex == 2 )
+ format = ImageFormat.Gif;
+ else if ( _saveFileDialog.FilterIndex == 3 )
+ format = ImageFormat.Jpeg;
+ else if ( _saveFileDialog.FilterIndex == 4 )
+ format = ImageFormat.Tiff;
+ else if ( _saveFileDialog.FilterIndex == 5 )
+ format = ImageFormat.Bmp;
+
+ Stream myStream = _saveFileDialog.OpenFile();
+ if ( myStream != null )
+ {
+ //_masterPane.GetImage().Save( myStream, format );
+ ImageRender().Save( myStream, format );
+ myStream.Close();
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Save Image As" context menu item. Copies the current image to the selected
+ /// Emf format file.
+ /// </summary>
+ /// <remarks>
+ /// Note that this handler saves as an Emf format only. The default handler is
+ /// <see cref="SaveAs()" />, which allows for Bitmap or EMF formats.
+ /// </remarks>
+ public void SaveAsEmf()
+ {
+ if ( _masterPane != null )
+ {
+ _saveFileDialog.Filter = "Emf Format (*.emf)|*.emf";
+
+ if ( _saveFileDialog.ShowDialog() == DialogResult.OK )
+ {
+ Stream myStream = _saveFileDialog.OpenFile();
+ if ( myStream != null )
+ {
+ myStream.Close();
+ //_masterPane.GetMetafile().Save( _saveFileDialog.FileName );
+ SaveEmfFile(_saveFileDialog.FileName);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Save the current Graph to the specified filename in EMF (vector) format.
+ /// See <see cref="SaveAsEmf()" /> for public access.
+ /// </summary>
+ /// <remarks>
+ /// Note that this handler saves as an Emf format only. The default handler is
+ /// <see cref="SaveAs()" />, which allows for Bitmap or EMF formats.
+ /// </remarks>
+ internal void SaveEmfFile( string fileName )
+ {
+ using (Graphics g = this.CreateGraphics())
+ {
+ IntPtr hdc = g.GetHdc();
+ Metafile metaFile = new Metafile(hdc, EmfType.EmfPlusOnly);
+ using (Graphics gMeta = Graphics.FromImage(metaFile))
+ {
+ //PaneBase.SetAntiAliasMode( gMeta, IsAntiAlias );
+ //gMeta.CompositingMode = CompositingMode.SourceCopy;
+ //gMeta.CompositingQuality = CompositingQuality.HighQuality;
+ //gMeta.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ //gMeta.SmoothingMode = SmoothingMode.AntiAlias;
+ //gMeta.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+ this._masterPane.Draw(gMeta);
+ //gMeta.Dispose();
+ }
+
+ ClipboardMetafileHelper.SaveEnhMetafileToFile(metaFile, fileName );
+
+ g.ReleaseHdc(hdc);
+ //g.Dispose();
+ }
+
+ }
+
+ internal class ClipboardMetafileHelper
+ {
+ [DllImport("user32.dll")]
+ static extern bool OpenClipboard(IntPtr hWndNewOwner);
+ [DllImport("user32.dll")]
+ static extern bool EmptyClipboard();
+ [DllImport("user32.dll")]
+ static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
+ [DllImport("user32.dll")]
+ static extern bool CloseClipboard();
+ [DllImport("gdi32.dll")]
+ static extern IntPtr CopyEnhMetaFile(IntPtr hemfSrc, System.Text.StringBuilder hNULL);
+ [DllImport("gdi32.dll")]
+ static extern bool DeleteEnhMetaFile(IntPtr hemf);
+
+ static internal bool SaveEnhMetafileToFile( Metafile mf, string fileName )
+ {
+ bool bResult = false;
+ IntPtr hEMF;
+ hEMF = mf.GetHenhmetafile(); // invalidates mf
+ if (!hEMF.Equals(new IntPtr(0)))
+ {
+ StringBuilder tempName = new StringBuilder(fileName);
+ CopyEnhMetaFile(hEMF, tempName);
+ DeleteEnhMetaFile(hEMF);
+ }
+ return bResult;
+ }
+
+ static internal bool SaveEnhMetafileToFile(Metafile mf)
+ {
+ bool bResult = false;
+ IntPtr hEMF;
+ hEMF = mf.GetHenhmetafile(); // invalidates mf
+ if (!hEMF.Equals(new IntPtr(0)))
+ {
+ SaveFileDialog sfd = new SaveFileDialog();
+ sfd.Filter = "Extended Metafile (*.emf)|*.emf";
+ sfd.DefaultExt = ".emf";
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ StringBuilder temp = new StringBuilder(sfd.FileName);
+ CopyEnhMetaFile(hEMF, temp);
+ }
+ DeleteEnhMetaFile(hEMF);
+ }
+ return bResult;
+ }
+
+ // Metafile mf is set to a state that is not valid inside this function.
+ static internal bool PutEnhMetafileOnClipboard(IntPtr hWnd, Metafile mf)
+ {
+ bool bResult = false;
+ IntPtr hEMF, hEMF2;
+ hEMF = mf.GetHenhmetafile(); // invalidates mf
+ if (!hEMF.Equals(new IntPtr(0)))
+ {
+ hEMF2 = CopyEnhMetaFile(hEMF, null);
+ if (!hEMF2.Equals(new IntPtr(0)))
+ {
+ if (OpenClipboard(hWnd))
+ {
+ if (EmptyClipboard())
+ {
+ IntPtr hRes = SetClipboardData(14 /*CF_ENHMETAFILE*/, hEMF2);
+ bResult = hRes.Equals(hEMF2);
+ CloseClipboard();
+ }
+ }
+ }
+ DeleteEnhMetaFile(hEMF);
+ }
+ return bResult;
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Show Values" context menu item. Toggles the <see cref="IsShowPointValues"/>
+ /// property, which activates the point value tooltips.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_ShowValues( object sender, System.EventArgs e )
+ {
+ ToolStripMenuItem item = sender as ToolStripMenuItem;
+ if ( item != null )
+ this.IsShowPointValues = !item.Checked;
+ }
+
+ /// <summary>
+ /// Handler for the "Set Scale to Default" context menu item. Sets the scale ranging to
+ /// full auto mode for all axes.
+ /// </summary>
+ /// <remarks>
+ /// This method differs from the <see cref="ZoomOutAll" /> method in that it sets the scales
+ /// to full auto mode. The <see cref="ZoomOutAll" /> method sets the scales to their initial
+ /// setting prior to any user actions (which may or may not be full auto mode).
+ /// </remarks>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_RestoreScale( object sender, EventArgs e )
+ {
+ if ( _masterPane != null )
+ {
+ GraphPane pane = _masterPane.FindPane( _menuClickPt );
+ RestoreScale( pane );
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Set Scale to Default" context menu item. Sets the scale ranging to
+ /// full auto mode for all axes.
+ /// </summary>
+ /// <remarks>
+ /// This method differs from the <see cref="ZoomOutAll" /> method in that it sets the scales
+ /// to full auto mode. The <see cref="ZoomOutAll" /> method sets the scales to their initial
+ /// setting prior to any user actions (which may or may not be full auto mode).
+ /// </remarks>
+ /// <param name="primaryPane">The <see cref="GraphPane" /> object which is to have the
+ /// scale restored</param>
+ public void RestoreScale( GraphPane primaryPane )
+ {
+ if ( primaryPane != null )
+ {
+ //Go ahead and save the old zoomstates, which provides an "undo"-like capability
+ //ZoomState oldState = primaryPane.ZoomStack.Push( primaryPane, ZoomState.StateType.Zoom );
+ ZoomState oldState = new ZoomState( primaryPane, ZoomState.StateType.Zoom );
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ pane.ZoomStack.Push( pane, ZoomState.StateType.Zoom );
+ ResetAutoScale( pane, g );
+ }
+ }
+ else
+ {
+ primaryPane.ZoomStack.Push( primaryPane, ZoomState.StateType.Zoom );
+ ResetAutoScale( primaryPane, g );
+ }
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, oldState, new ZoomState( primaryPane, ZoomState.StateType.Zoom ) );
+
+ //g.Dispose();
+ }
+ Refresh();
+ }
+ }
+
+ private void ResetAutoScale( GraphPane pane, Graphics g )
+ {
+ pane.XAxis.ResetAutoScale( pane, g );
+ pane.X2Axis.ResetAutoScale( pane, g );
+ foreach ( YAxis axis in pane.YAxisList )
+ axis.ResetAutoScale( pane, g );
+ foreach ( Y2Axis axis in pane.Y2AxisList )
+ axis.ResetAutoScale( pane, g );
+ }
+
+ /*
+ public void RestoreScale( GraphPane primaryPane )
+ {
+ if ( primaryPane != null )
+ {
+ Graphics g = this.CreateGraphics();
+ ZoomState oldState = new ZoomState( primaryPane, ZoomState.StateType.Zoom );
+ //ZoomState newState = null;
+
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ if ( pane == primaryPane )
+ {
+ pane.XAxis.ResetAutoScale( pane, g );
+ foreach ( YAxis axis in pane.YAxisList )
+ axis.ResetAutoScale( pane, g );
+ foreach ( Y2Axis axis in pane.Y2AxisList )
+ axis.ResetAutoScale( pane, g );
+ }
+ }
+ }
+ else
+ {
+ primaryPane.XAxis.ResetAutoScale( primaryPane, g );
+ foreach ( YAxis axis in primaryPane.YAxisList )
+ axis.ResetAutoScale( primaryPane, g );
+ foreach ( Y2Axis axis in primaryPane.Y2AxisList )
+ axis.ResetAutoScale( primaryPane, g );
+ }
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, oldState, new ZoomState( primaryPane, ZoomState.StateType.Zoom ) );
+
+ g.Dispose();
+ Refresh();
+ }
+ }
+ */
+ /*
+ public void ZoomOutAll( GraphPane primaryPane )
+ {
+ if ( primaryPane != null && !primaryPane.ZoomStack.IsEmpty )
+ {
+ ZoomState.StateType type = primaryPane.ZoomStack.Top.Type;
+
+ ZoomState oldState = new ZoomState( primaryPane, type );
+ //ZoomState newState = pane.ZoomStack.PopAll( pane );
+ ZoomState newState = null;
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ ZoomState state = pane.ZoomStack.PopAll( pane );
+ if ( pane == primaryPane )
+ newState = state;
+ }
+ }
+ else
+ newState = primaryPane.ZoomStack.PopAll( primaryPane );
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, oldState, newState );
+
+ Refresh();
+ }
+ }
+
+ */
+
+ /// <summary>
+ /// Handler for the "UnZoom/UnPan" context menu item. Restores the scale ranges to the values
+ /// before the last zoom or pan operation.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_ZoomOut( System.Object sender, System.EventArgs e )
+ {
+ if ( _masterPane != null )
+ {
+ GraphPane pane = _masterPane.FindPane( _menuClickPt );
+ ZoomOut( pane );
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "UnZoom/UnPan" context menu item. Restores the scale ranges to the values
+ /// before the last zoom, pan, or scroll operation.
+ /// </summary>
+ /// <remarks>
+ /// Triggers a <see cref="ZoomEvent" /> for any type of undo (including pan, scroll, zoom, and
+ /// wheelzoom). This method will affect all the
+ /// <see cref="GraphPane" /> objects in the <see cref="MasterPane" /> if
+ /// <see cref="IsSynchronizeXAxes" /> or <see cref="IsSynchronizeYAxes" /> is true.
+ /// </remarks>
+ /// <param name="primaryPane">The primary <see cref="GraphPane" /> object which is to be
+ /// zoomed out</param>
+ public void ZoomOut( GraphPane primaryPane )
+ {
+ if ( primaryPane != null && !primaryPane.ZoomStack.IsEmpty )
+ {
+ ZoomState.StateType type = primaryPane.ZoomStack.Top.Type;
+
+ ZoomState oldState = new ZoomState( primaryPane, type );
+ ZoomState newState = null;
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ ZoomState state = pane.ZoomStack.Pop( pane );
+ if ( pane == primaryPane )
+ newState = state;
+ }
+ }
+ else
+ newState = primaryPane.ZoomStack.Pop( primaryPane );
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, oldState, newState );
+
+ Refresh();
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Undo All Zoom/Pan" context menu item. Restores the scale ranges to the values
+ /// before all zoom and pan operations
+ /// </summary>
+ /// <remarks>
+ /// This method differs from the <see cref="RestoreScale" /> method in that it sets the scales
+ /// to their initial setting prior to any user actions. The <see cref="RestoreScale" /> method
+ /// sets the scales to full auto mode (regardless of what the initial setting may have been).
+ /// </remarks>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_ZoomOutAll( System.Object sender, System.EventArgs e )
+ {
+ if ( _masterPane != null )
+ {
+ GraphPane pane = _masterPane.FindPane( _menuClickPt );
+ ZoomOutAll( pane );
+ }
+ }
+
+ /// <summary>
+ /// Handler for the "Undo All Zoom/Pan" context menu item. Restores the scale ranges to the values
+ /// before all zoom and pan operations
+ /// </summary>
+ /// <remarks>
+ /// This method differs from the <see cref="RestoreScale" /> method in that it sets the scales
+ /// to their initial setting prior to any user actions. The <see cref="RestoreScale" /> method
+ /// sets the scales to full auto mode (regardless of what the initial setting may have been).
+ /// </remarks>
+ /// <param name="primaryPane">The <see cref="GraphPane" /> object which is to be zoomed out</param>
+ public void ZoomOutAll( GraphPane primaryPane )
+ {
+ if ( primaryPane != null && !primaryPane.ZoomStack.IsEmpty )
+ {
+ ZoomState.StateType type = primaryPane.ZoomStack.Top.Type;
+
+ ZoomState oldState = new ZoomState( primaryPane, type );
+ //ZoomState newState = pane.ZoomStack.PopAll( pane );
+ ZoomState newState = null;
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ ZoomState state = pane.ZoomStack.PopAll( pane );
+ if ( pane == primaryPane )
+ newState = state;
+ }
+ }
+ else
+ newState = primaryPane.ZoomStack.PopAll( primaryPane );
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, oldState, newState );
+
+ Refresh();
+ }
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/ZedGraphControl.Designer.cs b/ZedGraph/ZedGraphControl.Designer.cs
new file mode 100644
index 0000000..0b5a92f
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.Designer.cs
@@ -0,0 +1,78 @@
+namespace ZedGraph
+{
+ partial class ZedGraphControl
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ #region Component Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
+ this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
+ this.pointToolTip = new System.Windows.Forms.ToolTip( this.components );
+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip( this.components );
+ this.SuspendLayout();
+ //
+ // vScrollBar1
+ //
+ this.vScrollBar1.Location = new System.Drawing.Point( 128, 0 );
+ this.vScrollBar1.Name = "vScrollBar1";
+ this.vScrollBar1.Size = new System.Drawing.Size( 17, 128 );
+ this.vScrollBar1.TabIndex = 0;
+ //this.vScrollBar1.MouseCaptureChanged += new System.EventHandler( this.ScrollBarMouseCaptureChanged );
+ this.vScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler( this.vScrollBar1_Scroll );
+ //
+ // hScrollBar1
+ //
+ this.hScrollBar1.Location = new System.Drawing.Point( 0, 128 );
+ this.hScrollBar1.Name = "hScrollBar1";
+ this.hScrollBar1.Size = new System.Drawing.Size( 128, 17 );
+ this.hScrollBar1.TabIndex = 1;
+ //this.hScrollBar1.MouseCaptureChanged += new System.EventHandler( this.ScrollBarMouseCaptureChanged );
+ this.hScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler( this.hScrollBar1_Scroll );
+ //
+ // pointToolTip
+ //
+ this.pointToolTip.AutoPopDelay = 5000;
+ this.pointToolTip.InitialDelay = 100;
+ this.pointToolTip.ReshowDelay = 0;
+ //
+ // contextMenuStrip1
+ //
+ this.contextMenuStrip1.Name = "contextMenuStrip1";
+ this.contextMenuStrip1.Size = new System.Drawing.Size( 61, 4 );
+ this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler( this.contextMenuStrip1_Opening );
+ //
+ // ZedGraphControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ContextMenuStrip = this.contextMenuStrip1;
+ this.Controls.Add( this.hScrollBar1 );
+ this.Controls.Add( this.vScrollBar1 );
+ this.Name = "ZedGraphControl";
+ this.Resize += new System.EventHandler( this.ZedGraphControl_ReSize );
+ this.KeyUp += new System.Windows.Forms.KeyEventHandler( this.ZedGraphControl_KeyUp );
+ this.KeyDown += new System.Windows.Forms.KeyEventHandler( this.ZedGraphControl_KeyDown );
+ this.MouseWheel += new System.Windows.Forms.MouseEventHandler( this.ZedGraphControl_MouseWheel );
+ this.ResumeLayout( false );
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.VScrollBar vScrollBar1;
+ private System.Windows.Forms.HScrollBar hScrollBar1;
+ private System.Windows.Forms.ToolTip pointToolTip;
+ private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+ }
+}
diff --git a/ZedGraph/ZedGraphControl.Events.cs b/ZedGraph/ZedGraphControl.Events.cs
new file mode 100644
index 0000000..2e9434a
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.Events.cs
@@ -0,0 +1,1510 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2007 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace ZedGraph
+{
+ partial class ZedGraphControl
+ {
+
+ #region Events
+
+ /// <summary>
+ /// A delegate that allows subscribing methods to append or modify the context menu.
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="menuStrip">A reference to the <see cref="ContextMenuStrip"/> object
+ /// that contains the context menu.
+ /// </param>
+ /// <param name="mousePt">The point at which the mouse was clicked</param>
+ /// <param name="objState">The current context menu state</param>
+ /// <seealso cref="ContextMenuBuilder" />
+ public delegate void ContextMenuBuilderEventHandler( ZedGraphControl sender,
+ ContextMenuStrip menuStrip, Point mousePt, ContextMenuObjectState objState );
+ /// <summary>
+ /// Subscribe to this event to be able to modify the ZedGraph context menu.
+ /// </summary>
+ /// <remarks>
+ /// The context menu is built on the fly after a right mouse click. You can add menu items
+ /// to this menu by simply modifying the <see paramref="menu"/> parameter.
+ /// </remarks>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to this event to be able to modify the ZedGraph context menu" )]
+ public event ContextMenuBuilderEventHandler ContextMenuBuilder;
+
+ /// <summary>
+ /// A delegate that allows notification of zoom and pan events.
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="oldState">A <see cref="ZoomState"/> object that corresponds to the state of the
+ /// <see cref="GraphPane"/> before the zoom or pan event.</param>
+ /// <param name="newState">A <see cref="ZoomState"/> object that corresponds to the state of the
+ /// <see cref="GraphPane"/> after the zoom or pan event</param>
+ /// <seealso cref="ZoomEvent" />
+ public delegate void ZoomEventHandler( ZedGraphControl sender, ZoomState oldState,
+ ZoomState newState );
+
+ /// <summary>
+ /// Subscribe to this event to be notified when the <see cref="GraphPane"/> is zoomed or panned by the user,
+ /// either via a mouse drag operation or by the context menu commands.
+ /// </summary>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to this event to be notified when the graph is zoomed or panned" )]
+ public event ZoomEventHandler ZoomEvent;
+
+ /// <summary>
+ /// A delegate that allows notification of scroll events.
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="scrollBar">The source <see cref="ScrollBar"/> object</param>
+ /// <param name="oldState">A <see cref="ZoomState"/> object that corresponds to the state of the
+ /// <see cref="GraphPane"/> before the scroll event.</param>
+ /// <param name="newState">A <see cref="ZoomState"/> object that corresponds to the state of the
+ /// <see cref="GraphPane"/> after the scroll event</param>
+ /// <seealso cref="ZoomEvent" />
+ public delegate void ScrollDoneHandler( ZedGraphControl sender, ScrollBar scrollBar,
+ ZoomState oldState, ZoomState newState );
+
+ /// <summary>
+ /// Subscribe to this event to be notified when the <see cref="GraphPane"/> is scrolled by the user
+ /// using the scrollbars.
+ /// </summary>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe this event to be notified when a scroll operation using the scrollbars is completed" )]
+ public event ScrollDoneHandler ScrollDoneEvent;
+
+ /// <summary>
+ /// A delegate that allows notification of scroll events.
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="scrollBar">The source <see cref="ScrollBar"/> object</param>
+ /// <param name="oldState">A <see cref="ZoomState"/> object that corresponds to the state of the
+ /// <see cref="GraphPane"/> before the scroll event.</param>
+ /// <param name="newState">A <see cref="ZoomState"/> object that corresponds to the state of the
+ /// <see cref="GraphPane"/> after the scroll event</param>
+ /// <seealso cref="ZoomEvent" />
+ public delegate void ScrollProgressHandler( ZedGraphControl sender, ScrollBar scrollBar,
+ ZoomState oldState, ZoomState newState );
+
+ /// <summary>
+ /// Subscribe to this event to be notified when the <see cref="GraphPane"/> is scrolled by the user
+ /// using the scrollbars.
+ /// </summary>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe this event to be notified continuously as a scroll operation is taking place" )]
+ public event ScrollProgressHandler ScrollProgressEvent;
+
+ /// <summary>
+ /// Subscribe to this event to be notified when the <see cref="GraphPane"/> is scrolled by the user
+ /// using the scrollbars.
+ /// </summary>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe this event to be notified of general scroll events" )]
+ public event ScrollEventHandler ScrollEvent;
+
+ /// <summary>
+ /// A delegate that receives notification after a point-edit operation is completed.
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="pane">The <see cref="GraphPane"/> object that contains the
+ /// point that has been edited</param>
+ /// <param name="curve">The <see cref="CurveItem"/> object that contains the point
+ /// that has been edited</param>
+ /// <param name="iPt">The integer index of the edited <see cref="PointPair"/> within the
+ /// <see cref="IPointList"/> of the selected <see cref="CurveItem"/>
+ /// </param>
+ /// <seealso cref="PointValueEvent" />
+ public delegate string PointEditHandler( ZedGraphControl sender, GraphPane pane,
+ CurveItem curve, int iPt );
+
+ /// <summary>
+ /// Subscribe to this event to receive notifcation and/or respond after a data
+ /// point has been edited via <see cref="IsEnableHEdit" /> and <see cref="IsEnableVEdit" />.
+ /// </summary>
+ /// <example>
+ /// <para>To subscribe to this event, use the following in your Form_Load method:</para>
+ /// <code>zedGraphControl1.PointEditEvent +=
+ /// new ZedGraphControl.PointEditHandler( MyPointEditHandler );</code>
+ /// <para>Add this method to your Form1.cs:</para>
+ /// <code>
+ /// private string MyPointEditHandler( object sender, GraphPane pane, CurveItem curve, int iPt )
+ /// {
+ /// PointPair pt = curve[iPt];
+ /// return "This value is " + pt.Y.ToString("f2") + " gallons";
+ /// }</code>
+ /// </example>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to this event to respond to data point edit actions" )]
+ public event PointEditHandler PointEditEvent;
+
+ /// <summary>
+ /// A delegate that allows custom formatting of the point value tooltips
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="pane">The <see cref="GraphPane"/> object that contains the point value of interest</param>
+ /// <param name="curve">The <see cref="CurveItem"/> object that contains the point value of interest</param>
+ /// <param name="iPt">The integer index of the selected <see cref="PointPair"/> within the
+ /// <see cref="IPointList"/> of the selected <see cref="CurveItem"/></param>
+ /// <seealso cref="PointValueEvent" />
+ public delegate string PointValueHandler( ZedGraphControl sender, GraphPane pane,
+ CurveItem curve, int iPt );
+
+ /// <summary>
+ /// Subscribe to this event to provide custom formatting for the tooltips
+ /// </summary>
+ /// <example>
+ /// <para>To subscribe to this event, use the following in your FormLoad method:</para>
+ /// <code>zedGraphControl1.PointValueEvent +=
+ /// new ZedGraphControl.PointValueHandler( MyPointValueHandler );</code>
+ /// <para>Add this method to your Form1.cs:</para>
+ /// <code>
+ /// private string MyPointValueHandler( object sender, GraphPane pane, CurveItem curve, int iPt )
+ /// {
+ /// #region
+ /// PointPair pt = curve[iPt];
+ /// return "This value is " + pt.Y.ToString("f2") + " gallons";
+ /// #endregion
+ /// }</code>
+ /// </example>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to this event to provide custom-formatting for data point tooltips" )]
+ public event PointValueHandler PointValueEvent;
+
+ /// <summary>
+ /// A delegate that allows custom formatting of the cursor value tooltips
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="pane">The <see cref="GraphPane"/> object that contains the cursor of interest</param>
+ /// <param name="mousePt">The <see cref="Point"/> object that represents the cursor value location</param>
+ /// <seealso cref="CursorValueEvent" />
+ public delegate string CursorValueHandler( ZedGraphControl sender, GraphPane pane,
+ Point mousePt );
+
+ /// <summary>
+ /// Subscribe to this event to provide custom formatting for the cursor value tooltips
+ /// </summary>
+ /// <example>
+ /// <para>To subscribe to this event, use the following in your FormLoad method:</para>
+ /// <code>zedGraphControl1.CursorValueEvent +=
+ /// new ZedGraphControl.CursorValueHandler( MyCursorValueHandler );</code>
+ /// <para>Add this method to your Form1.cs:</para>
+ /// <code>
+ /// private string MyCursorValueHandler( object sender, GraphPane pane, Point mousePt )
+ /// {
+ /// #region
+ /// double x, y;
+ /// pane.ReverseTransform( mousePt, out x, out y );
+ /// return "( " + x.ToString( "f2" ) + ", " + y.ToString( "f2" ) + " )";
+ /// #endregion
+ /// }</code>
+ /// </example>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to this event to provide custom-formatting for cursor value tooltips" )]
+ public event CursorValueHandler CursorValueEvent;
+
+ /// <summary>
+ /// A delegate that allows notification of mouse events on Graph objects.
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="e">A <see cref="MouseEventArgs" /> corresponding to this event</param>
+ /// <seealso cref="MouseDownEvent" />
+ /// <returns>
+ /// Return true if you have handled the mouse event entirely, and you do not
+ /// want the <see cref="ZedGraphControl"/> to do any further action (e.g., starting
+ /// a zoom operation). Return false if ZedGraph should go ahead and process the
+ /// mouse event.
+ /// </returns>
+ public delegate bool ZedMouseEventHandler( ZedGraphControl sender, MouseEventArgs e );
+
+ /// <summary>
+ /// Subscribe to this event to provide notification of MouseDown clicks on graph
+ /// objects
+ /// </summary>
+ /// <remarks>
+ /// This event provides for a notification when the mouse is clicked on an object
+ /// within any <see cref="GraphPane"/> of the <see cref="MasterPane"/> associated
+ /// with this <see cref="ZedGraphControl" />. This event will use the
+ /// <see cref="ZedGraph.MasterPane.FindNearestPaneObject"/> method to determine which object
+ /// was clicked. The boolean value that you return from this handler determines whether
+ /// or not the <see cref="ZedGraphControl"/> will do any further handling of the
+ /// MouseDown event (see <see cref="ZedMouseEventHandler" />). Return true if you have
+ /// handled the MouseDown event entirely, and you do not
+ /// want the <see cref="ZedGraphControl"/> to do any further action (e.g., starting
+ /// a zoom operation). Return false if ZedGraph should go ahead and process the
+ /// MouseDown event.
+ /// </remarks>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to be notified when the left mouse button is clicked down" )]
+ public event ZedMouseEventHandler MouseDownEvent;
+
+ /// <summary>
+ /// Hide the standard control MouseDown event so that the ZedGraphControl.MouseDownEvent
+ /// can be used. This is so that the user must return true/false in order to indicate
+ /// whether or not we should respond to the event.
+ /// </summary>
+ [Bindable( false ), Browsable( false )]
+ public new event MouseEventHandler MouseDown;
+ /// <summary>
+ /// Hide the standard control MouseUp event so that the ZedGraphControl.MouseUpEvent
+ /// can be used. This is so that the user must return true/false in order to indicate
+ /// whether or not we should respond to the event.
+ /// </summary>
+ [Bindable( false ), Browsable( false )]
+ public new event MouseEventHandler MouseUp;
+ /// <summary>
+ /// Hide the standard control MouseMove event so that the ZedGraphControl.MouseMoveEvent
+ /// can be used. This is so that the user must return true/false in order to indicate
+ /// whether or not we should respond to the event.
+ /// </summary>
+ [Bindable( false ), Browsable( false )]
+ private new event MouseEventHandler MouseMove;
+ /// <summary>
+ /// Subscribe to this event to provide notification of MouseUp clicks on graph
+ /// objects
+ /// </summary>
+ /// <remarks>
+ /// This event provides for a notification when the mouse is clicked on an object
+ /// within any <see cref="GraphPane"/> of the <see cref="MasterPane"/> associated
+ /// with this <see cref="ZedGraphControl" />. This event will use the
+ /// <see cref="ZedGraph.MasterPane.FindNearestPaneObject"/> method to determine which object
+ /// was clicked. The boolean value that you return from this handler determines whether
+ /// or not the <see cref="ZedGraphControl"/> will do any further handling of the
+ /// MouseUp event (see <see cref="ZedMouseEventHandler" />). Return true if you have
+ /// handled the MouseUp event entirely, and you do not
+ /// want the <see cref="ZedGraphControl"/> to do any further action (e.g., starting
+ /// a zoom operation). Return false if ZedGraph should go ahead and process the
+ /// MouseUp event.
+ /// </remarks>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to be notified when the left mouse button is released" )]
+ public event ZedMouseEventHandler MouseUpEvent;
+ /// <summary>
+ /// Subscribe to this event to provide notification of MouseMove events over graph
+ /// objects
+ /// </summary>
+ /// <remarks>
+ /// This event provides for a notification when the mouse is moving over on the control.
+ /// The boolean value that you return from this handler determines whether
+ /// or not the <see cref="ZedGraphControl"/> will do any further handling of the
+ /// MouseMove event (see <see cref="ZedMouseEventHandler" />). Return true if you
+ /// have handled the MouseMove event entirely, and you do not
+ /// want the <see cref="ZedGraphControl"/> to do any further action.
+ /// Return false if ZedGraph should go ahead and process the MouseMove event.
+ /// </remarks>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to be notified when the mouse is moved inside the control" )]
+ public event ZedMouseEventHandler MouseMoveEvent;
+
+ /// <summary>
+ /// Subscribe to this event to provide notification of Double Clicks on graph
+ /// objects
+ /// </summary>
+ /// <remarks>
+ /// This event provides for a notification when the mouse is double-clicked on an object
+ /// within any <see cref="GraphPane"/> of the <see cref="MasterPane"/> associated
+ /// with this <see cref="ZedGraphControl" />. This event will use the
+ /// <see cref="ZedGraph.MasterPane.FindNearestPaneObject"/> method to determine which object
+ /// was clicked. The boolean value that you return from this handler determines whether
+ /// or not the <see cref="ZedGraphControl"/> will do any further handling of the
+ /// DoubleClick event (see <see cref="ZedMouseEventHandler" />). Return true if you have
+ /// handled the DoubleClick event entirely, and you do not
+ /// want the <see cref="ZedGraphControl"/> to do any further action.
+ /// Return false if ZedGraph should go ahead and process the
+ /// DoubleClick event.
+ /// </remarks>
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to be notified when the left mouse button is double-clicked" )]
+ public event ZedMouseEventHandler DoubleClickEvent;
+
+ /// <summary>
+ /// A delegate that allows notification of clicks on ZedGraph objects that have
+ /// active links enabled
+ /// </summary>
+ /// <param name="sender">The source <see cref="ZedGraphControl"/> object</param>
+ /// <param name="pane">The source <see cref="GraphPane" /> in which the click
+ /// occurred.
+ /// </param>
+ /// <param name="source">The source object which was clicked. This is typically
+ /// a type of <see cref="CurveItem" /> if a curve point was clicked, or
+ /// a type of <see cref="GraphObj" /> if a graph object was clicked.
+ /// </param>
+ /// <param name="link">The <see cref="Link" /> object, belonging to
+ /// <paramref name="source" />, that contains the link information
+ /// </param>
+ /// <param name="index">An index value, typically used if a <see cref="CurveItem" />
+ /// was clicked, indicating the ordinal value of the actual point that was clicked.
+ /// </param>
+ /// <returns>
+ /// Return true if you have handled the LinkEvent entirely, and you do not
+ /// want the <see cref="ZedGraphControl"/> to do any further action.
+ /// Return false if ZedGraph should go ahead and process the LinkEvent.
+ /// </returns>
+ public delegate bool LinkEventHandler( ZedGraphControl sender, GraphPane pane,
+ object source, Link link, int index );
+
+ /// <summary>
+ /// Subscribe to this event to be able to respond to mouse clicks within linked
+ /// objects.
+ /// </summary>
+ /// <remarks>
+ /// Linked objects are typically either <see cref="GraphObj" /> type objects or
+ /// <see cref="CurveItem" /> type objects. These object types can include
+ /// hyperlink information allowing for "drill-down" type operation.
+ /// </remarks>
+ /// <seealso cref="LinkEventHandler"/>
+ /// <seealso cref="Link" />
+ /// <seealso cref="CurveItem.Link">CurveItem.Link</seealso>
+ /// <seealso cref="GraphObj.Link">GraphObj.Link</seealso>
+ // /// <seealso cref="ZedGraph.Web.IsImageMap" />
+ [Bindable( true ), Category( "Events" ),
+ Description( "Subscribe to be notified when a link-enabled item is clicked" )]
+ public event LinkEventHandler LinkEvent;
+
+ #endregion
+
+ #region Mouse Events
+
+ /// <summary>
+ /// Handle a MouseDown event in the <see cref="ZedGraphControl" />
+ /// </summary>
+ /// <param name="sender">A reference to the <see cref="ZedGraphControl" /></param>
+ /// <param name="e">A <see cref="MouseEventArgs" /> instance</param>
+ protected void ZedGraphControl_MouseDown( object sender, MouseEventArgs e )
+ {
+ _isPanning = false;
+ _isZooming = false;
+ _isEditing = false;
+ _isSelecting = false;
+ _dragPane = null;
+
+ Point mousePt = new Point( e.X, e.Y );
+
+ // Callback for doubleclick events
+ if ( _masterPane != null && e.Clicks > 1 && this.DoubleClickEvent != null )
+ {
+ if ( this.DoubleClickEvent( this, e ) )
+ return;
+ }
+
+ // Provide Callback for MouseDown events
+ if ( _masterPane != null && this.MouseDownEvent != null )
+ {
+ if ( this.MouseDownEvent( this, e ) )
+ return;
+ }
+
+ if ( e.Clicks > 1 || _masterPane == null )
+ return;
+
+ // First, see if the click is within a Linkable object within any GraphPane
+ GraphPane pane = this.MasterPane.FindPane( mousePt );
+ if ( pane != null &&
+ e.Button == _linkButtons && Control.ModifierKeys == _linkModifierKeys )
+ {
+ object source;
+ Link link;
+ int index;
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ float scaleFactor = pane.CalcScaleFactor();
+ if ( pane.FindLinkableObject( mousePt, g, scaleFactor, out source, out link, out index ) )
+ {
+ if ( LinkEvent != null && LinkEvent( this, pane, source, link, index ) )
+ return;
+
+ string url;
+ CurveItem curve = source as CurveItem;
+
+ if ( curve != null )
+ url = link.MakeCurveItemUrl( pane, curve, index );
+ else
+ url = link._url;
+
+ if ( url != string.Empty )
+ {
+ System.Diagnostics.Process.Start( url );
+ // linkable objects override any other actions with mouse
+ return;
+ }
+ }
+ //g.Dispose();
+ }
+ }
+
+ // Second, Check to see if it's within a Chart Rect
+ pane = this.MasterPane.FindChartRect( mousePt );
+ //Rectangle rect = new Rectangle( mousePt, new Size( 1, 1 ) );
+
+ if ( pane != null &&
+ ( _isEnableHPan || _isEnableVPan ) &&
+ ( ( e.Button == _panButtons && Control.ModifierKeys == _panModifierKeys ) ||
+ ( e.Button == _panButtons2 && Control.ModifierKeys == _panModifierKeys2 ) ) )
+ {
+ _isPanning = true;
+ _dragStartPt = mousePt;
+ _dragPane = pane;
+ //_zoomState = new ZoomState( _dragPane, ZoomState.StateType.Pan );
+ ZoomStateSave( _dragPane, ZoomState.StateType.Pan );
+ }
+ else if ( pane != null && ( _isEnableHZoom || _isEnableVZoom ) &&
+ ( ( e.Button == _zoomButtons && Control.ModifierKeys == _zoomModifierKeys ) ||
+ ( e.Button == _zoomButtons2 && Control.ModifierKeys == _zoomModifierKeys2 ) ) )
+ {
+ _isZooming = true;
+ _dragStartPt = mousePt;
+ _dragEndPt = mousePt;
+ _dragEndPt.Offset( 1, 1 );
+ _dragPane = pane;
+ ZoomStateSave( _dragPane, ZoomState.StateType.Zoom );
+ }
+ //Revision: JCarpenter 10/06
+ else if ( pane != null && _isEnableSelection && e.Button == _selectButtons &&
+ ( Control.ModifierKeys == _selectModifierKeys ||
+ Control.ModifierKeys == _selectAppendModifierKeys ) )
+ {
+ _isSelecting = true;
+ _dragStartPt = mousePt;
+ _dragEndPt = mousePt;
+ _dragEndPt.Offset( 1, 1 );
+ _dragPane = pane;
+ }
+ else if ( pane != null && ( _isEnableHEdit || _isEnableVEdit ) &&
+ ( e.Button == EditButtons && Control.ModifierKeys == EditModifierKeys ) )
+ {
+
+ // find the point that was clicked, and make sure the point list is editable
+ // and that it's a primary Y axis (the first Y or Y2 axis)
+ if ( pane.FindNearestPoint( mousePt, out _dragCurve, out _dragIndex ) &&
+ _dragCurve.Points is IPointListEdit )
+ {
+ _isEditing = true;
+ _dragPane = pane;
+ _dragStartPt = mousePt;
+ _dragStartPair = _dragCurve[_dragIndex];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Set the cursor according to the current mouse location.
+ /// </summary>
+ protected void SetCursor()
+ {
+ SetCursor( this.PointToClient( Control.MousePosition ) );
+ }
+
+ /// <summary>
+ /// Set the cursor according to the current mouse location.
+ /// </summary>
+ protected void SetCursor( Point mousePt )
+ {
+ if ( _masterPane != null )
+ {
+ GraphPane pane = _masterPane.FindChartRect( mousePt );
+ if ( ( _isEnableHPan || _isEnableVPan ) && ( Control.ModifierKeys == Keys.Shift || _isPanning ) &&
+ ( pane != null || _isPanning ) )
+ this.Cursor = Cursors.Hand;
+ else if ( ( _isEnableVZoom || _isEnableHZoom ) && ( pane != null || _isZooming ) )
+ this.Cursor = Cursors.Cross;
+ else if ( _isEnableSelection && ( pane != null || _isSelecting ) )
+ this.Cursor = Cursors.Cross;
+ else
+ this.Cursor = Cursors.Default;
+
+ // else if ( isZoomMode || isPanMode )
+ // this.Cursor = Cursors.No;
+ }
+ }
+
+ /// <summary>
+ /// Handle a KeyUp event
+ /// </summary>
+ /// <param name="sender">The <see cref="ZedGraphControl" /> in which the KeyUp occurred.</param>
+ /// <param name="e">A <see cref="KeyEventArgs" /> instance.</param>
+ protected void ZedGraphControl_KeyUp( object sender, KeyEventArgs e )
+ {
+ SetCursor();
+ }
+
+ /// <summary>
+ /// Handle the Key Events so ZedGraph can Escape out of a panning or zooming operation.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void ZedGraphControl_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e )
+ {
+ SetCursor();
+
+ if ( e.KeyCode == Keys.Escape )
+ {
+ if ( _isPanning )
+ HandlePanCancel();
+ if ( _isZooming )
+ HandleZoomCancel();
+ if ( _isEditing )
+ HandleEditCancel();
+ //if ( _isSelecting )
+ // Esc always cancels the selection
+ HandleSelectionCancel();
+
+ _isZooming = false;
+ _isPanning = false;
+ _isEditing = false;
+ _isSelecting = false;
+
+ Refresh();
+ }
+ }
+
+ /// <summary>
+ /// Handle a MouseUp event in the <see cref="ZedGraphControl" />
+ /// </summary>
+ /// <param name="sender">A reference to the <see cref="ZedGraphControl" /></param>
+ /// <param name="e">A <see cref="MouseEventArgs" /> instance</param>
+ protected void ZedGraphControl_MouseUp( object sender, MouseEventArgs e )
+ {
+ // Provide Callback for MouseUp events
+ if ( _masterPane != null && this.MouseUpEvent != null )
+ {
+ if ( this.MouseUpEvent( this, e ) )
+ return;
+ }
+
+ if ( _masterPane != null && _dragPane != null )
+ {
+ // If the MouseUp event occurs, the user is done dragging.
+ if ( _isZooming )
+ HandleZoomFinish( sender, e );
+ else if ( _isPanning )
+ HandlePanFinish();
+ else if ( _isEditing )
+ HandleEditFinish();
+ //Revision: JCarpenter 10/06
+ else if ( _isSelecting )
+ HandleSelectionFinish( sender, e );
+ }
+
+ // Reset the rectangle.
+ //dragStartPt = new Rectangle( 0, 0, 0, 0 );
+ _dragPane = null;
+ _isZooming = false;
+ _isPanning = false;
+ _isEditing = false;
+ _isSelecting = false;
+
+ Cursor.Current = Cursors.Default;
+ }
+
+ /// <summary>
+ /// Make a string label that corresponds to a user scale value.
+ /// </summary>
+ /// <param name="axis">The axis from which to obtain the scale value. This determines
+ /// if it's a date value, linear, log, etc.</param>
+ /// <param name="val">The value to be made into a label</param>
+ /// <param name="iPt">The ordinal position of the value</param>
+ /// <param name="isOverrideOrdinal">true to override the ordinal settings of the axis,
+ /// and prefer the actual value instead.</param>
+ /// <returns>The string label.</returns>
+ protected string MakeValueLabel( Axis axis, double val, int iPt, bool isOverrideOrdinal )
+ {
+ if ( axis != null )
+ {
+ if ( axis.Scale.IsDate || axis.Scale.Type == AxisType.DateAsOrdinal )
+ {
+ return XDate.ToString( val, _pointDateFormat );
+ }
+ else if ( axis._scale.IsText && axis._scale._textLabels != null )
+ {
+ int i = iPt;
+ if ( isOverrideOrdinal )
+ i = (int)( val - 0.5 );
+
+ if ( i >= 0 && i < axis._scale._textLabels.Length )
+ return axis._scale._textLabels[i];
+ else
+ return ( i + 1 ).ToString();
+ }
+ else if ( axis.Scale.IsAnyOrdinal && axis.Scale.Type != AxisType.LinearAsOrdinal
+ && !isOverrideOrdinal )
+ {
+ return iPt.ToString( _pointValueFormat );
+ }
+ else
+ return val.ToString( _pointValueFormat );
+ }
+ else
+ return "";
+ }
+
+ /// <summary>
+ /// protected method for handling MouseMove events to display tooltips over
+ /// individual datapoints.
+ /// </summary>
+ /// <param name="sender">
+ /// A reference to the control that has the MouseMove event.
+ /// </param>
+ /// <param name="e">
+ /// A MouseEventArgs object.
+ /// </param>
+ protected void ZedGraphControl_MouseMove( object sender, MouseEventArgs e )
+ {
+ if ( _masterPane != null )
+ {
+ Point mousePt = new Point( e.X, e.Y );
+
+ // Provide Callback for MouseMove events
+ if ( this.MouseMoveEvent != null && this.MouseMoveEvent( this, e ) )
+ return;
+
+ //Point tempPt = this.PointToClient( Control.MousePosition );
+
+ SetCursor( mousePt );
+
+ // If the mouse is being dragged,
+ // undraw and redraw the rectangle as the mouse moves.
+ if ( _isZooming )
+ HandleZoomDrag( mousePt );
+ else if ( _isPanning )
+ HandlePanDrag( mousePt );
+ else if ( _isEditing )
+ HandleEditDrag( mousePt );
+ else if ( _isShowCursorValues )
+ HandleCursorValues( mousePt );
+ else if ( _isShowPointValues )
+ HandlePointValues( mousePt );
+ //Revision: JCarpenter 10/06
+ else if ( _isSelecting )
+ HandleZoomDrag( mousePt );
+ }
+ }
+
+ private Point HandlePointValues( Point mousePt )
+ {
+ int iPt;
+ GraphPane pane;
+ object nearestObj;
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+
+ if ( _masterPane.FindNearestPaneObject( mousePt,
+ g, out pane, out nearestObj, out iPt ) )
+ {
+ if ( nearestObj is CurveItem && iPt >= 0 )
+ {
+ CurveItem curve = (CurveItem)nearestObj;
+ // Provide Callback for User to customize the tooltips
+ if ( this.PointValueEvent != null )
+ {
+ string label = this.PointValueEvent( this, pane, curve, iPt );
+ if ( label != null && label.Length > 0 )
+ {
+ this.pointToolTip.SetToolTip( this, label );
+ this.pointToolTip.Active = true;
+ }
+ else
+ this.pointToolTip.Active = false;
+ }
+ else
+ {
+
+ if ( curve is PieItem )
+ {
+ this.pointToolTip.SetToolTip( this,
+ ( (PieItem)curve ).Value.ToString( _pointValueFormat ) );
+ }
+ // else if ( curve is OHLCBarItem || curve is JapaneseCandleStickItem )
+ // {
+ // StockPt spt = (StockPt)curve.Points[iPt];
+ // this.pointToolTip.SetToolTip( this, ( (XDate) spt.Date ).ToString( "MM/dd/yyyy" ) + "\nOpen: $" +
+ // spt.Open.ToString( "N2" ) +
+ // "\nHigh: $" +
+ // spt.High.ToString( "N2" ) + "\nLow: $" +
+ // spt.Low.ToString( "N2" ) + "\nClose: $" +
+ // spt.Close.ToString
+ // ( "N2" ) );
+ // }
+ else
+ {
+ PointPair pt = curve.Points[iPt];
+
+ if ( pt.Tag is string )
+ this.pointToolTip.SetToolTip( this, (string)pt.Tag );
+ else
+ {
+ double xVal, yVal, lowVal;
+ ValueHandler valueHandler = new ValueHandler( pane, false );
+ if ( ( curve is BarItem || curve is ErrorBarItem || curve is HiLowBarItem )
+ && pane.BarSettings.Base != BarBase.X )
+ valueHandler.GetValues( curve, iPt, out yVal, out lowVal, out xVal );
+ else
+ valueHandler.GetValues( curve, iPt, out xVal, out lowVal, out yVal );
+
+ string xStr = MakeValueLabel( curve.GetXAxis( pane ), xVal, iPt,
+ curve.IsOverrideOrdinal );
+ string yStr = MakeValueLabel( curve.GetYAxis( pane ), yVal, iPt,
+ curve.IsOverrideOrdinal );
+
+ this.pointToolTip.SetToolTip( this, "( " + xStr + ", " + yStr + " )" );
+
+ //this.pointToolTip.SetToolTip( this,
+ // curve.Points[iPt].ToString( this.pointValueFormat ) );
+ }
+ }
+
+ this.pointToolTip.Active = true;
+ }
+ }
+ else
+ this.pointToolTip.Active = false;
+ }
+ else
+ this.pointToolTip.Active = false;
+
+ //g.Dispose();
+ }
+ return mousePt;
+ }
+
+ private Point HandleCursorValues( Point mousePt )
+ {
+ GraphPane pane = _masterPane.FindPane( mousePt );
+ if ( pane != null && pane.Chart._rect.Contains( mousePt ) )
+ {
+ // Provide Callback for User to customize the tooltips
+ if ( this.CursorValueEvent != null )
+ {
+ string label = this.CursorValueEvent( this, pane, mousePt );
+ if ( label != null && label.Length > 0 )
+ {
+ this.pointToolTip.SetToolTip( this, label );
+ this.pointToolTip.Active = true;
+ }
+ else
+ this.pointToolTip.Active = false;
+ }
+ else
+ {
+ double x, x2, y, y2;
+ pane.ReverseTransform( mousePt, out x, out x2, out y, out y2 );
+ string xStr = MakeValueLabel( pane.XAxis, x, -1, true );
+ string yStr = MakeValueLabel( pane.YAxis, y, -1, true );
+ string y2Str = MakeValueLabel( pane.Y2Axis, y2, -1, true );
+
+ this.pointToolTip.SetToolTip( this, "( " + xStr + ", " + yStr + ", " + y2Str + " )" );
+ this.pointToolTip.Active = true;
+ }
+ }
+ else
+ this.pointToolTip.Active = false;
+
+ return mousePt;
+ }
+
+
+ #endregion
+
+ #region Mouse Wheel Zoom Events
+
+ /// <summary>
+ /// Handle a MouseWheel event in the <see cref="ZedGraphControl" />
+ /// </summary>
+ /// <param name="sender">A reference to the <see cref="ZedGraphControl" /></param>
+ /// <param name="e">A <see cref="MouseEventArgs" /> instance</param>
+ protected void ZedGraphControl_MouseWheel( object sender, MouseEventArgs e )
+ {
+ if ( ( _isEnableVZoom || _isEnableHZoom ) && _isEnableWheelZoom && _masterPane != null )
+ {
+ GraphPane pane = this.MasterPane.FindChartRect( new PointF( e.X, e.Y ) );
+ if ( pane != null && e.Delta != 0 )
+ {
+ ZoomState oldState = ZoomStateSave( pane, ZoomState.StateType.WheelZoom );
+ //ZoomState oldState = pane.ZoomStack.Push( pane, ZoomState.StateType.Zoom );
+
+ PointF centerPoint = new PointF( e.X, e.Y );
+ double zoomFraction = ( 1 + ( e.Delta < 0 ? 1.0 : -1.0 ) * ZoomStepFraction );
+
+ ZoomPane( pane, zoomFraction, centerPoint, _isZoomOnMouseCenter, false );
+
+ ApplyToAllPanes( pane );
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ // always AxisChange() the dragPane
+ pane.AxisChange( g );
+
+ foreach ( GraphPane tempPane in _masterPane._paneList )
+ {
+ if ( tempPane != pane && ( _isSynchronizeXAxes || _isSynchronizeYAxes ) )
+ tempPane.AxisChange( g );
+ }
+ }
+
+ ZoomStatePush( pane );
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, oldState, new ZoomState( pane, ZoomState.StateType.WheelZoom ) );
+
+ this.Refresh();
+
+ }
+ }
+ }
+
+ /// <summary>
+ /// Zoom a specified pane in or out according to the specified zoom fraction.
+ /// </summary>
+ /// <remarks>
+ /// The zoom will occur on the <see cref="XAxis" />, <see cref="YAxis" />, and
+ /// <see cref="Y2Axis" /> only if the corresponding flag, <see cref="IsEnableHZoom" /> or
+ /// <see cref="IsEnableVZoom" />, is true. Note that if there are multiple Y or Y2 axes, all of
+ /// them will be zoomed.
+ /// </remarks>
+ /// <param name="pane">The <see cref="GraphPane" /> instance to be zoomed.</param>
+ /// <param name="zoomFraction">The fraction by which to zoom, less than 1 to zoom in, greater than
+ /// 1 to zoom out. For example, 0.9 will zoom in such that the scale is 90% of what it was
+ /// originally.</param>
+ /// <param name="centerPt">The screen position about which the zoom will be centered. This
+ /// value is only used if <see paramref="isZoomOnCenter" /> is true.
+ /// </param>
+ /// <param name="isZoomOnCenter">true to cause the zoom to be centered on the point
+ /// <see paramref="centerPt" />, false to center on the <see cref="Chart.Rect" />.
+ /// </param>
+ /// <param name="isRefresh">true to force a refresh of the control, false to leave it unrefreshed</param>
+ protected void ZoomPane( GraphPane pane, double zoomFraction, PointF centerPt,
+ bool isZoomOnCenter, bool isRefresh )
+ {
+ double x;
+ double x2;
+ double[] y;
+ double[] y2;
+
+ pane.ReverseTransform( centerPt, out x, out x2, out y, out y2 );
+
+ if ( _isEnableHZoom )
+ {
+ ZoomScale( pane.XAxis, zoomFraction, x, isZoomOnCenter );
+ ZoomScale( pane.X2Axis, zoomFraction, x2, isZoomOnCenter );
+ }
+ if ( _isEnableVZoom )
+ {
+ for ( int i = 0; i < pane.YAxisList.Count; i++ )
+ ZoomScale( pane.YAxisList[i], zoomFraction, y[i], isZoomOnCenter );
+ for ( int i = 0; i < pane.Y2AxisList.Count; i++ )
+ ZoomScale( pane.Y2AxisList[i], zoomFraction, y2[i], isZoomOnCenter );
+ }
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ pane.AxisChange( g );
+ //g.Dispose();
+ }
+
+ this.SetScroll( this.hScrollBar1, pane.XAxis, _xScrollRange.Min, _xScrollRange.Max );
+ this.SetScroll( this.vScrollBar1, pane.YAxis, _yScrollRangeList[0].Min,
+ _yScrollRangeList[0].Max );
+
+ if ( isRefresh )
+ Refresh();
+ }
+
+ /// <summary>
+ /// Zoom a specified pane in or out according to the specified zoom fraction.
+ /// </summary>
+ /// <remarks>
+ /// The zoom will occur on the <see cref="XAxis" />, <see cref="YAxis" />, and
+ /// <see cref="Y2Axis" /> only if the corresponding flag, <see cref="IsEnableHZoom" /> or
+ /// <see cref="IsEnableVZoom" />, is true. Note that if there are multiple Y or Y2 axes, all of
+ /// them will be zoomed.
+ /// </remarks>
+ /// <param name="pane">The <see cref="GraphPane" /> instance to be zoomed.</param>
+ /// <param name="zoomFraction">The fraction by which to zoom, less than 1 to zoom in, greater than
+ /// 1 to zoom out. For example, 0.9 will zoom in such that the scale is 90% of what it was
+ /// originally.</param>
+ /// <param name="centerPt">The screen position about which the zoom will be centered. This
+ /// value is only used if <see paramref="isZoomOnCenter" /> is true.
+ /// </param>
+ /// <param name="isZoomOnCenter">true to cause the zoom to be centered on the point
+ /// <see paramref="centerPt" />, false to center on the <see cref="Chart.Rect" />.
+ /// </param>
+ public void ZoomPane( GraphPane pane, double zoomFraction, PointF centerPt, bool isZoomOnCenter )
+ {
+ ZoomPane( pane, zoomFraction, centerPt, isZoomOnCenter, true );
+ }
+
+
+ /// <summary>
+ /// Zoom the specified axis by the specified amount, with the center of the zoom at the
+ /// (optionally) specified point.
+ /// </summary>
+ /// <remarks>
+ /// This method is used for MouseWheel zoom operations</remarks>
+ /// <param name="axis">The <see cref="Axis" /> to be zoomed.</param>
+ /// <param name="zoomFraction">The zoom fraction, less than 1.0 to zoom in, greater than 1.0 to
+ /// zoom out. That is, a value of 0.9 will zoom in such that the scale length is 90% of what
+ /// it previously was.</param>
+ /// <param name="centerVal">The location for the center of the zoom. This is only used if
+ /// <see paramref="IsZoomOnMouseCenter" /> is true.</param>
+ /// <param name="isZoomOnCenter">true if the zoom is to be centered at the
+ /// <see paramref="centerVal" /> screen position, false for the zoom to be centered within
+ /// the <see cref="Chart.Rect" />.
+ /// </param>
+ protected void ZoomScale( Axis axis, double zoomFraction, double centerVal, bool isZoomOnCenter )
+ {
+ if ( axis != null && zoomFraction > 0.0001 && zoomFraction < 1000.0 )
+ {
+ Scale scale = axis._scale;
+ /*
+ if ( axis.Scale.IsLog )
+ {
+ double ratio = Math.Sqrt( axis._scale._max / axis._scale._min * zoomFraction );
+
+ if ( !isZoomOnCenter )
+ centerVal = Math.Sqrt( axis._scale._max * axis._scale._min );
+
+ axis._scale._min = centerVal / ratio;
+ axis._scale._max = centerVal * ratio;
+ }
+ else
+ {
+ */
+ double minLin = axis._scale._minLinearized;
+ double maxLin = axis._scale._maxLinearized;
+ double range = ( maxLin - minLin ) * zoomFraction / 2.0;
+
+ if ( !isZoomOnCenter )
+ centerVal = ( maxLin + minLin ) / 2.0;
+
+ axis._scale._minLinearized = centerVal - range;
+ axis._scale._maxLinearized = centerVal + range;
+ // }
+
+ axis._scale._minAuto = false;
+ axis._scale._maxAuto = false;
+ }
+ }
+
+ #endregion
+
+ #region Pan Events
+
+ private Point HandlePanDrag( Point mousePt )
+ {
+ double x1, x2, xx1, xx2;
+ double[] y1, y2, yy1, yy2;
+ //PointF endPoint = mousePt;
+ //PointF startPoint = ( (Control)sender ).PointToClient( this.dragRect.Location );
+
+ _dragPane.ReverseTransform( _dragStartPt, out x1, out xx1, out y1, out yy1 );
+ _dragPane.ReverseTransform( mousePt, out x2, out xx2, out y2, out yy2 );
+
+ if ( _isEnableHPan )
+ {
+ PanScale( _dragPane.XAxis, x1, x2 );
+ PanScale( _dragPane.X2Axis, xx1, xx2 );
+ this.SetScroll( this.hScrollBar1, _dragPane.XAxis, _xScrollRange.Min, _xScrollRange.Max );
+ }
+ if ( _isEnableVPan )
+ {
+ for ( int i = 0; i < y1.Length; i++ )
+ PanScale( _dragPane.YAxisList[i], y1[i], y2[i] );
+ for ( int i = 0; i < yy1.Length; i++ )
+ PanScale( _dragPane.Y2AxisList[i], yy1[i], yy2[i] );
+ this.SetScroll( this.vScrollBar1, _dragPane.YAxis, _yScrollRangeList[0].Min,
+ _yScrollRangeList[0].Max );
+ }
+
+ ApplyToAllPanes( _dragPane );
+
+ Refresh();
+
+ _dragStartPt = mousePt;
+
+ return mousePt;
+ }
+
+ private void HandlePanFinish()
+ {
+ // push the prior saved zoomstate, since the scale ranges have already been changed on
+ // the fly during the panning operation
+ if ( _zoomState != null && _zoomState.IsChanged( _dragPane ) )
+ {
+ //_dragPane.ZoomStack.Push( _zoomState );
+ ZoomStatePush( _dragPane );
+
+ // Provide Callback to notify the user of pan events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, _zoomState,
+ new ZoomState( _dragPane, ZoomState.StateType.Pan ) );
+
+ _zoomState = null;
+ }
+ }
+
+ private void HandlePanCancel()
+ {
+ if ( _isPanning )
+ {
+ if ( _zoomState != null && _zoomState.IsChanged( _dragPane ) )
+ {
+ ZoomStateRestore( _dragPane );
+ //_zoomState.ApplyState( _dragPane );
+ //_zoomState = null;
+ }
+ _isPanning = false;
+ Refresh();
+
+ ZoomStateClear();
+ }
+ }
+
+ /// <summary>
+ /// Handle a panning operation for the specified <see cref="Axis" />.
+ /// </summary>
+ /// <param name="axis">The <see cref="Axis" /> to be panned</param>
+ /// <param name="startVal">The value where the pan started. The scale range
+ /// will be shifted by the difference between <see paramref="startVal" /> and
+ /// <see paramref="endVal" />.
+ /// </param>
+ /// <param name="endVal">The value where the pan ended. The scale range
+ /// will be shifted by the difference between <see paramref="startVal" /> and
+ /// <see paramref="endVal" />.
+ /// </param>
+ protected void PanScale( Axis axis, double startVal, double endVal )
+ {
+ if ( axis != null )
+ {
+ Scale scale = axis._scale;
+ double delta = scale.Linearize( startVal ) - scale.Linearize( endVal );
+
+ scale._minLinearized += delta;
+ scale._maxLinearized += delta;
+
+ scale._minAuto = false;
+ scale._maxAuto = false;
+
+ /*
+ if ( axis.Type == AxisType.Log )
+ {
+ axis._scale._min *= startVal / endVal;
+ axis._scale._max *= startVal / endVal;
+ }
+ else
+ {
+ axis._scale._min += startVal - endVal;
+ axis._scale._max += startVal - endVal;
+ }
+ */
+ }
+ }
+
+ #endregion
+
+ #region Edit Point Events
+
+ private void HandleEditDrag( Point mousePt )
+ {
+ // get the scale values that correspond to the current point
+ double curX, curY;
+ _dragPane.ReverseTransform( mousePt, _dragCurve.IsX2Axis, _dragCurve.IsY2Axis,
+ _dragCurve.YAxisIndex, out curX, out curY );
+ double startX, startY;
+ _dragPane.ReverseTransform( _dragStartPt, _dragCurve.IsX2Axis, _dragCurve.IsY2Axis,
+ _dragCurve.YAxisIndex, out startX, out startY );
+
+ // calculate the new scale values for the point
+ PointPair newPt = new PointPair( _dragStartPair );
+
+ Scale xScale = _dragCurve.GetXAxis( _dragPane )._scale;
+ if ( _isEnableHEdit )
+ newPt.X = xScale.DeLinearize( xScale.Linearize( newPt.X ) +
+ xScale.Linearize( curX ) - xScale.Linearize( startX ) );
+
+ Scale yScale = _dragCurve.GetYAxis( _dragPane )._scale;
+ if ( _isEnableVEdit )
+ newPt.Y = yScale.DeLinearize( yScale.Linearize( newPt.Y ) +
+ yScale.Linearize( curY ) - yScale.Linearize( startY ) );
+
+ // save the data back to the point list
+ IPointListEdit list = _dragCurve.Points as IPointListEdit;
+ if ( list != null )
+ list[_dragIndex] = newPt;
+
+ // force a redraw
+ Refresh();
+ }
+
+ private void HandleEditFinish()
+ {
+ if ( this.PointEditEvent != null )
+ this.PointEditEvent( this, _dragPane, _dragCurve, _dragIndex );
+ }
+
+ private void HandleEditCancel()
+ {
+ if ( _isEditing )
+ {
+ IPointListEdit list = _dragCurve.Points as IPointListEdit;
+ if ( list != null )
+ list[_dragIndex] = _dragStartPair;
+ _isEditing = false;
+ Refresh();
+ }
+ }
+
+ #endregion
+
+ #region Zoom Events
+
+ private void HandleZoomDrag( Point mousePt )
+ {
+ // Hide the previous rectangle by calling the
+ // DrawReversibleFrame method with the same parameters.
+ Rectangle rect = CalcScreenRect( _dragStartPt, _dragEndPt );
+ ControlPaint.DrawReversibleFrame( rect, this.BackColor, FrameStyle.Dashed );
+
+ // Bound the zoom to the ChartRect
+ _dragEndPt = Point.Round( BoundPointToRect( mousePt, _dragPane.Chart._rect ) );
+ rect = CalcScreenRect( _dragStartPt, _dragEndPt );
+ // Draw the new rectangle by calling DrawReversibleFrame again.
+ ControlPaint.DrawReversibleFrame( rect, this.BackColor, FrameStyle.Dashed );
+ }
+
+ private const double ZoomResolution = 1e-300;
+
+ private void HandleZoomFinish( object sender, MouseEventArgs e )
+ {
+ PointF mousePtF = BoundPointToRect( new Point( e.X, e.Y ), _dragPane.Chart._rect );
+
+ // Only accept a drag if it covers at least 5 pixels in each direction
+ //Point curPt = ( (Control)sender ).PointToScreen( Point.Round( mousePt ) );
+ if ( ( Math.Abs( mousePtF.X - _dragStartPt.X ) > 4 || !_isEnableHZoom ) &&
+ ( Math.Abs( mousePtF.Y - _dragStartPt.Y ) > 4 || !_isEnableVZoom ) )
+ {
+ // Draw the rectangle to be evaluated. Set a dashed frame style
+ // using the FrameStyle enumeration.
+ //ControlPaint.DrawReversibleFrame( this.dragRect,
+ // this.BackColor, FrameStyle.Dashed );
+
+ double x1, x2, xx1, xx2;
+ double[] y1, y2, yy1, yy2;
+ //PointF startPoint = ( (Control)sender ).PointToClient( this.dragRect.Location );
+
+ _dragPane.ReverseTransform( _dragStartPt, out x1, out xx1, out y1, out yy1 );
+ _dragPane.ReverseTransform( mousePtF, out x2, out xx2, out y2, out yy2 );
+
+ bool zoomLimitExceeded = false;
+
+ if ( _isEnableHZoom )
+ {
+ double min1 = Math.Min( x1, x2 );
+ double max1 = Math.Max( x1, x2 );
+ double min2 = Math.Min( xx1, xx2 );
+ double max2 = Math.Max( xx1, xx2 );
+
+ if ( Math.Abs( x1 - x2 ) < ZoomResolution || Math.Abs( xx1 - xx2 ) < ZoomResolution )
+ zoomLimitExceeded = true;
+ }
+
+ if ( _isEnableVZoom && !zoomLimitExceeded )
+ {
+ for ( int i = 0; i < y1.Length; i++ )
+ {
+ if ( Math.Abs( y1[i] - y2[i] ) < ZoomResolution )
+ {
+ zoomLimitExceeded = true;
+ break;
+ }
+ }
+ for ( int i = 0; i < yy1.Length; i++ )
+ {
+ if ( Math.Abs( yy1[i] - yy2[i] ) < ZoomResolution )
+ {
+ zoomLimitExceeded = true;
+ break;
+ }
+ }
+ }
+
+ if ( !zoomLimitExceeded )
+ {
+
+ ZoomStatePush( _dragPane );
+ //ZoomState oldState = _dragPane.ZoomStack.Push( _dragPane,
+ // ZoomState.StateType.Zoom );
+
+
+ if ( _isEnableHZoom )
+ {
+ _dragPane.XAxis._scale._min = Math.Min( x1, x2 );
+ _dragPane.XAxis._scale._minAuto = false;
+ _dragPane.XAxis._scale._max = Math.Max( x1, x2 );
+ _dragPane.XAxis._scale._maxAuto = false;
+
+ _dragPane.X2Axis._scale._min = Math.Min( xx1, xx2 );
+ _dragPane.X2Axis._scale._minAuto = false;
+ _dragPane.X2Axis._scale._max = Math.Max( xx1, xx2 );
+ _dragPane.X2Axis._scale._maxAuto = false;
+ }
+
+ if ( _isEnableVZoom )
+ {
+ for ( int i = 0; i < y1.Length; i++ )
+ {
+ _dragPane.YAxisList[i]._scale._min = Math.Min( y1[i], y2[i] );
+ _dragPane.YAxisList[i]._scale._max = Math.Max( y1[i], y2[i] );
+ _dragPane.YAxisList[i]._scale._minAuto = false;
+ _dragPane.YAxisList[i]._scale._maxAuto = false;
+ }
+ for ( int i = 0; i < yy1.Length; i++ )
+ {
+ _dragPane.Y2AxisList[i]._scale._min = Math.Min( yy1[i], yy2[i] );
+ _dragPane.Y2AxisList[i]._scale._max = Math.Max( yy1[i], yy2[i] );
+ _dragPane.Y2AxisList[i]._scale._minAuto = false;
+ _dragPane.Y2AxisList[i]._scale._maxAuto = false;
+ }
+ }
+
+ this.SetScroll( this.hScrollBar1, _dragPane.XAxis, _xScrollRange.Min, _xScrollRange.Max );
+ this.SetScroll( this.vScrollBar1, _dragPane.YAxis, _yScrollRangeList[0].Min,
+ _yScrollRangeList[0].Max );
+
+ ApplyToAllPanes( _dragPane );
+
+ // Provide Callback to notify the user of zoom events
+ if ( this.ZoomEvent != null )
+ this.ZoomEvent( this, _zoomState, //oldState,
+ new ZoomState( _dragPane, ZoomState.StateType.Zoom ) );
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ // always AxisChange() the dragPane
+ _dragPane.AxisChange( g );
+
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ if ( pane != _dragPane && ( _isSynchronizeXAxes || _isSynchronizeYAxes ) )
+ pane.AxisChange( g );
+ }
+ }
+ }
+
+ Refresh();
+ }
+ }
+
+ private void HandleZoomCancel()
+ {
+ if ( _isZooming )
+ {
+ _isZooming = false;
+ Refresh();
+
+ ZoomStateClear();
+ }
+ }
+
+ private PointF BoundPointToRect( Point mousePt, RectangleF rect )
+ {
+ PointF newPt = new PointF( mousePt.X, mousePt.Y );
+
+ if ( mousePt.X < rect.X ) newPt.X = rect.X;
+ if ( mousePt.X > rect.Right ) newPt.X = rect.Right;
+ if ( mousePt.Y < rect.Y ) newPt.Y = rect.Y;
+ if ( mousePt.Y > rect.Bottom ) newPt.Y = rect.Bottom;
+
+ return newPt;
+ }
+
+ private Rectangle CalcScreenRect( Point mousePt1, Point mousePt2 )
+ {
+ Point screenPt = PointToScreen( mousePt1 );
+ Size size = new Size( mousePt2.X - mousePt1.X, mousePt2.Y - mousePt1.Y );
+ Rectangle rect = new Rectangle( screenPt, size );
+
+ if ( _isZooming )
+ {
+ Rectangle chartRect = Rectangle.Round( _dragPane.Chart._rect );
+
+ Point chartPt = PointToScreen( chartRect.Location );
+
+ if ( !_isEnableVZoom )
+ {
+ rect.Y = chartPt.Y;
+ rect.Height = chartRect.Height + 1;
+ }
+ else if ( !_isEnableHZoom )
+ {
+ rect.X = chartPt.X;
+ rect.Width = chartRect.Width + 1;
+ }
+ }
+
+ return rect;
+ }
+
+ #endregion
+
+ #region Selection Events
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Perform selection on curves within the drag pane, or under the mouse click.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void HandleSelectionFinish( object sender, MouseEventArgs e )
+ {
+ if ( e.Button != _selectButtons )
+ {
+ Refresh();
+ return;
+ }
+
+ PointF mousePtF = BoundPointToRect( new Point( e.X, e.Y ), _dragPane.Chart._rect );
+
+ PointF mousePt = BoundPointToRect( new Point( e.X, e.Y ), _dragPane.Rect );
+
+ Point curPt = ( (Control)sender ).PointToScreen( Point.Round( mousePt ) );
+
+ // Only accept a drag if it covers at least 5 pixels in each direction
+ //Point curPt = ( (Control)sender ).PointToScreen( Point.Round( mousePt ) );
+ if ( ( Math.Abs( mousePtF.X - _dragStartPt.X ) > 4 ) &&
+ ( Math.Abs( mousePtF.Y - _dragStartPt.Y ) > 4 ) )
+ {
+
+ #region New Code to Select on Rubber Band
+
+ double x1, x2, xx1, xx2;
+ double[] y1, y2, yy1, yy2;
+ PointF startPoint = ( (Control)sender ).PointToClient( new Point( Convert.ToInt32( this._dragPane.Rect.X ), Convert.ToInt32( this._dragPane.Rect.Y ) ) );
+
+ _dragPane.ReverseTransform( _dragStartPt, out x1, out xx1, out y1, out yy1 );
+ _dragPane.ReverseTransform( mousePtF, out x2, out xx2, out y2, out yy2 );
+
+ CurveList objects = new CurveList();
+
+ double left = Math.Min( x1, x2 );
+ double right = Math.Max( x1, x2 );
+
+ double top = 0;
+ double bottom = 0;
+
+ for ( int i = 0; i < y1.Length; i++ )
+ {
+ bottom = Math.Min( y1[i], y2[i] );
+ top = Math.Max( y1[i], y2[i] );
+ }
+
+ for ( int i = 0; i < yy1.Length; i++ )
+ {
+ bottom = Math.Min( bottom, yy2[i] );
+ bottom = Math.Min( yy1[i], bottom );
+ top = Math.Max( top, yy2[i] );
+ top = Math.Max( yy1[i], top );
+ }
+
+ double w = right - left;
+ double h = bottom - top;
+
+ RectangleF rF = new RectangleF( (float)left, (float)top, (float)w, (float)h );
+
+ _dragPane.FindContainedObjects( rF, this.CreateGraphics(), out objects );
+
+ if ( Control.ModifierKeys == _selectAppendModifierKeys )
+ _selection.AddToSelection( _masterPane, objects );
+ else
+ _selection.Select( _masterPane, objects );
+ // this.Select( objects );
+
+ //Graphics g = this.CreateGraphics();
+ //this._dragPane.AxisChange( g );
+ //g.Dispose();
+
+ #endregion
+ }
+ else // It's a single-select
+ {
+ #region New Code to Single Select
+
+ //Point mousePt = new Point( e.X, e.Y );
+
+ int iPt;
+ GraphPane pane;
+ object nearestObj;
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ if ( this.MasterPane.FindNearestPaneObject( mousePt, g, out pane,
+ out nearestObj, out iPt ) )
+ {
+ if ( nearestObj is CurveItem && iPt >= 0 )
+ {
+ if ( Control.ModifierKeys == _selectAppendModifierKeys )
+ _selection.AddToSelection( _masterPane, nearestObj as CurveItem );
+ else
+ _selection.Select( _masterPane, nearestObj as CurveItem );
+ }
+ else
+ _selection.ClearSelection( _masterPane );
+
+ Refresh();
+ }
+ else
+ {
+ _selection.ClearSelection( _masterPane );
+ }
+ }
+ #endregion New Code to Single Select
+ }
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ // always AxisChange() the dragPane
+ _dragPane.AxisChange( g );
+
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ if ( pane != _dragPane && ( _isSynchronizeXAxes || _isSynchronizeYAxes ) )
+ pane.AxisChange( g );
+ }
+ }
+
+ Refresh();
+ }
+
+ private void HandleSelectionCancel()
+ {
+ _isSelecting = false;
+
+ _selection.ClearSelection( _masterPane );
+
+ Refresh();
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ZedGraphControl.Printing.cs b/ZedGraph/ZedGraphControl.Printing.cs
new file mode 100644
index 0000000..92f00b6
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.Printing.cs
@@ -0,0 +1,240 @@
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+using System.Drawing.Imaging;
+using System.Drawing.Printing;
+using System.Threading;
+
+namespace ZedGraph
+{
+ partial class ZedGraphControl
+ {
+
+ #region Printing
+
+ /// <summary>
+ /// Handler for the "Page Setup..." context menu item. Displays a
+ /// <see cref="PageSetupDialog" />.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_PageSetup( object sender, EventArgs e )
+ {
+ DoPageSetup();
+ }
+
+ /// <summary>
+ /// Handler for the "Print..." context menu item. Displays a
+ /// <see cref="PrintDialog" />.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ protected void MenuClick_Print( object sender, EventArgs e )
+ {
+ DoPrint();
+ }
+
+ /// <summary>
+ /// Rendering method used by the print context menu items
+ /// </summary>
+ /// <param name="sender">The applicable <see cref="PrintDocument" />.</param>
+ /// <param name="e">A <see cref="PrintPageEventArgs" /> instance providing
+ /// page bounds, margins, and a Graphics instance for this printed output.
+ /// </param>
+ private void Graph_PrintPage( object sender, PrintPageEventArgs e )
+ {
+ PrintDocument pd = sender as PrintDocument;
+
+ MasterPane mPane = this.MasterPane;
+ bool[] isPenSave = new bool[mPane.PaneList.Count + 1];
+ bool[] isFontSave = new bool[mPane.PaneList.Count + 1];
+ isPenSave[0] = mPane.IsPenWidthScaled;
+ isFontSave[0] = mPane.IsFontsScaled;
+ for ( int i = 0; i < mPane.PaneList.Count; i++ )
+ {
+ isPenSave[i + 1] = mPane[i].IsPenWidthScaled;
+ isFontSave[i + 1] = mPane[i].IsFontsScaled;
+ if ( _isPrintScaleAll )
+ {
+ mPane[i].IsPenWidthScaled = true;
+ mPane[i].IsFontsScaled = true;
+ }
+ }
+
+ RectangleF saveRect = mPane.Rect;
+ SizeF newSize = mPane.Rect.Size;
+ if ( _isPrintFillPage && _isPrintKeepAspectRatio )
+ {
+ float xRatio = (float)e.MarginBounds.Width / (float)newSize.Width;
+ float yRatio = (float)e.MarginBounds.Height / (float)newSize.Height;
+ float ratio = Math.Min( xRatio, yRatio );
+
+ newSize.Width *= ratio;
+ newSize.Height *= ratio;
+ }
+ else if ( _isPrintFillPage )
+ newSize = e.MarginBounds.Size;
+
+ mPane.ReSize( e.Graphics, new RectangleF( e.MarginBounds.Left,
+ e.MarginBounds.Top, newSize.Width, newSize.Height ) );
+ mPane.Draw( e.Graphics );
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ mPane.ReSize( g, saveRect );
+ //g.Dispose();
+ }
+
+ mPane.IsPenWidthScaled = isPenSave[0];
+ mPane.IsFontsScaled = isFontSave[0];
+ for ( int i = 0; i < mPane.PaneList.Count; i++ )
+ {
+ mPane[i].IsPenWidthScaled = isPenSave[i + 1];
+ mPane[i].IsFontsScaled = isFontSave[i + 1];
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Printing.PrintDocument" /> instance
+ /// that is used for all of the context menu printing functions.
+ /// </summary>
+ public PrintDocument PrintDocument
+ {
+ get
+ {
+ // Add a try/catch pair since the users of the control can't catch this one
+ try
+ {
+ if ( _pdSave == null )
+ {
+ _pdSave = new PrintDocument();
+ _pdSave.PrintPage += new PrintPageEventHandler( Graph_PrintPage );
+ }
+ }
+ catch ( Exception exception )
+ {
+ MessageBox.Show( exception.Message );
+ }
+
+ return _pdSave;
+ }
+ set { _pdSave = value; }
+ }
+
+ /// <summary>
+ /// Display a <see cref="PageSetupDialog" /> to the user, allowing them to modify
+ /// the print settings for this <see cref="ZedGraphControl" />.
+ /// </summary>
+ public void DoPageSetup()
+ {
+ PrintDocument pd = PrintDocument;
+
+ // Add a try/catch pair since the users of the control can't catch this one
+ try
+ {
+ if ( pd != null )
+ {
+ //pd.PrintPage += new PrintPageEventHandler( GraphPrintPage );
+ PageSetupDialog setupDlg = new PageSetupDialog();
+ setupDlg.Document = pd;
+
+ if ( setupDlg.ShowDialog() == DialogResult.OK )
+ {
+ pd.PrinterSettings = setupDlg.PrinterSettings;
+ pd.DefaultPageSettings = setupDlg.PageSettings;
+
+ // BUG in PrintDocument!!! Converts in/mm repeatedly
+ // http://support.microsoft.com/?id=814355
+ // from http://www.vbinfozine.com/tpagesetupdialog.shtml, by Palo Mraz
+ //if ( System.Globalization.RegionInfo.CurrentRegion.IsMetric )
+ //{
+ // setupDlg.Document.DefaultPageSettings.Margins = PrinterUnitConvert.Convert(
+ // setupDlg.Document.DefaultPageSettings.Margins,
+ // PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter );
+ //}
+ }
+ }
+ }
+
+ catch ( Exception exception )
+ {
+ MessageBox.Show( exception.Message );
+ }
+ }
+
+ /// <summary>
+ /// Display a <see cref="PrintDialog" /> to the user, allowing them to select a
+ /// printer and print the <see cref="MasterPane" /> contained in this
+ /// <see cref="ZedGraphControl" />.
+ /// </summary>
+ public void DoPrint()
+ {
+ // Add a try/catch pair since the users of the control can't catch this one
+ try
+ {
+ PrintDocument pd = PrintDocument;
+
+ if ( pd != null )
+ {
+ //pd.PrintPage += new PrintPageEventHandler( Graph_PrintPage );
+ PrintDialog pDlg = new PrintDialog();
+ pDlg.Document = pd;
+ if ( pDlg.ShowDialog() == DialogResult.OK )
+ pd.Print();
+ }
+ }
+ catch ( Exception exception )
+ {
+ MessageBox.Show( exception.Message );
+ }
+
+ }
+
+ /// <summary>
+ /// Display a <see cref="PrintPreviewDialog" />, allowing the user to preview and
+ /// subsequently print the <see cref="MasterPane" /> contained in this
+ /// <see cref="ZedGraphControl" />.
+ /// </summary>
+ public void DoPrintPreview()
+ {
+ // Add a try/catch pair since the users of the control can't catch this one
+ try
+ {
+ PrintDocument pd = PrintDocument;
+
+ if ( pd != null )
+ {
+ PrintPreviewDialog ppd = new PrintPreviewDialog();
+ //pd.PrintPage += new PrintPageEventHandler( Graph_PrintPage );
+ ppd.Document = pd;
+ ppd.Show( this );
+ }
+ }
+ catch ( Exception exception )
+ {
+ MessageBox.Show( exception.Message );
+ }
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/ZedGraphControl.Properties.cs b/ZedGraph/ZedGraphControl.Properties.cs
new file mode 100644
index 0000000..53a94bc
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.Properties.cs
@@ -0,0 +1,1231 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2007 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace ZedGraph
+{
+ partial class ZedGraphControl
+ {
+
+ #region Button and Key Properties
+
+ /// <summary>
+ /// Gets or sets a value that determines which mouse button will be used as a primary option
+ /// to trigger a zoom event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="ZoomModifierKeys"/> to determine the actual zoom combination.
+ /// A secondary zoom button/key combination option is available via <see cref="ZoomButtons2"/> and
+ /// <see cref="ZoomModifierKeys2"/>. To not use this button/key combination, set the value
+ /// of <see cref="ZoomButtons"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.Left ),
+ Description( "Determines which mouse button is used as the primary for zooming" )]
+ public MouseButtons ZoomButtons
+ {
+ get { return _zoomButtons; }
+ set { _zoomButtons = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which mouse button will be used as the secondary option
+ /// to trigger a zoom event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="ZoomModifierKeys2"/> to determine the actual zoom combination.
+ /// The primary zoom button/key combination option is available via <see cref="ZoomButtons"/> and
+ /// <see cref="ZoomModifierKeys"/>. To not use this button/key combination, set the value
+ /// of <see cref="ZoomButtons2"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.None ),
+ Description( "Determines which mouse button is used as the secondary for zooming" )]
+ public MouseButtons ZoomButtons2
+ {
+ get { return _zoomButtons2; }
+ set { _zoomButtons2 = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used as a primary option
+ /// to trigger a zoom event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="ZoomButtons"/> to determine the actual zoom combination.
+ /// A secondary zoom button/key combination option is available via <see cref="ZoomButtons2"/> and
+ /// <see cref="ZoomModifierKeys2"/>. To not use this button/key combination, set the value
+ /// of <see cref="ZoomButtons"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.None ),
+ Description( "Determines which modifier key used as the primary for zooming" )]
+ public Keys ZoomModifierKeys
+ {
+ get { return _zoomModifierKeys; }
+ set { _zoomModifierKeys = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used as a secondary option
+ /// to trigger a zoom event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="ZoomButtons2"/> to determine the actual zoom combination.
+ /// A primary zoom button/key combination option is available via <see cref="ZoomButtons"/> and
+ /// <see cref="ZoomModifierKeys"/>. To not use this button/key combination, set the value
+ /// of <see cref="ZoomButtons2"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.None ),
+ Description( "Determines which modifier key used as the secondary for zooming" )]
+ public Keys ZoomModifierKeys2
+ {
+ get { return _zoomModifierKeys2; }
+ set { _zoomModifierKeys2 = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which mouse button will be used as a primary option
+ /// to trigger a pan event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="PanModifierKeys"/> to determine the actual pan combination.
+ /// A secondary pan button/key combination option is available via <see cref="PanButtons2"/> and
+ /// <see cref="PanModifierKeys2"/>. To not use this button/key combination, set the value
+ /// of <see cref="PanButtons"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.Left ),
+ Description( "Determines which mouse button is used as the primary for panning" )]
+ public MouseButtons PanButtons
+ {
+ get { return _panButtons; }
+ set { _panButtons = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which mouse button will be used as the secondary option
+ /// to trigger a pan event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="PanModifierKeys2"/> to determine the actual pan combination.
+ /// The primary pan button/key combination option is available via <see cref="PanButtons"/> and
+ /// <see cref="PanModifierKeys"/>. To not use this button/key combination, set the value
+ /// of <see cref="PanButtons2"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.Middle ),
+ Description( "Determines which mouse button is used as the secondary for panning" )]
+ public MouseButtons PanButtons2
+ {
+ get { return _panButtons2; }
+ set { _panButtons2 = value; }
+ }
+
+ // NOTE: The default value of PanModifierKeys is Keys.Shift. Because of an apparent bug in
+ // VS 2003, the initial value set in InitializeComponent by the code wizard is "Keys.Shift+None"
+ // which will not compile. As a temporary workaround, I've hidden the value so that it won't
+ // have compile errors. This problem does not exist in VS 2005.
+
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used as a primary option
+ /// to trigger a pan event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="PanButtons"/> to determine the actual pan combination.
+ /// A secondary pan button/key combination option is available via <see cref="PanButtons2"/> and
+ /// <see cref="PanModifierKeys2"/>. To not use this button/key combination, set the value
+ /// of <see cref="PanButtons"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.Control ),
+ Description( "Determines which modifier key is used as the primary for panning" )]
+ public Keys PanModifierKeys
+ {
+ get { return _panModifierKeys; }
+ set { _panModifierKeys = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used as a secondary option
+ /// to trigger a pan event.
+ /// </summary>
+ /// <remarks>
+ /// This value is combined with <see cref="PanButtons2"/> to determine the actual pan combination.
+ /// A primary pan button/key combination option is available via <see cref="PanButtons"/> and
+ /// <see cref="PanModifierKeys"/>. To not use this button/key combination, set the value
+ /// of <see cref="PanButtons2"/> to <see cref="MouseButtons.None"/>.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.None ),
+ Description( "Determines which modifier key is used as the secondary for panning" )]
+ public Keys PanModifierKeys2
+ {
+ get { return _panModifierKeys2; }
+ set { _panModifierKeys2 = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to edit point
+ /// data values
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHEdit" /> and/or
+ /// <see cref="IsEnableVEdit" /> are true.
+ /// </remarks>
+ /// <seealso cref="EditModifierKeys" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.Right ),
+ Description( "Specify mouse button for point editing" )]
+ public MouseButtons EditButtons
+ {
+ get { return _editButtons; }
+ set { _editButtons = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to edit point
+ /// data values
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHEdit" /> and/or
+ /// <see cref="IsEnableVEdit" /> are true.
+ /// </remarks>
+ /// <seealso cref="EditButtons" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.Alt ),
+ Description( "Specify modifier key for point editing" )]
+ public Keys EditModifierKeys
+ {
+ get { return _editModifierKeys; }
+ set { _editModifierKeys = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to
+ /// select <see cref="CurveItem" />'s.
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableSelection" /> is true.
+ /// </remarks>
+ /// <seealso cref="SelectModifierKeys" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.Left ),
+ Description( "Specify mouse button for curve selection" )]
+ public MouseButtons SelectButtons
+ {
+ get { return _selectButtons; }
+ set { _selectButtons = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which Modifier keys will be used to
+ /// select <see cref="CurveItem" />'s.
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableSelection" /> is true.
+ /// </remarks>
+ /// <seealso cref="SelectButtons" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.Shift ),
+ Description( "Specify modifier key for curve selection" )]
+ public Keys SelectModifierKeys
+ {
+ get { return _selectModifierKeys; }
+ set { _selectModifierKeys = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which Modifier keys will be used to
+ /// append a <see cref="CurveItem" /> to the selection list.
+ /// </summary>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.Shift | Keys.Alt ),
+ Description( "Specify modifier key for append curve selection" )]
+ public Keys SelectAppendModifierKeys
+ {
+ get { return _selectAppendModifierKeys; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to click
+ /// on linkable objects
+ /// </summary>
+ /// <seealso cref="LinkModifierKeys" />
+ /// <seealso cref="LinkEvent"/>
+ // /// <seealso cref="ZedGraph.Web.IsImageMap"/>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( MouseButtons.Left ),
+ Description( "Specify mouse button for clicking on linkable objects" )]
+ public MouseButtons LinkButtons
+ {
+ get { return _linkButtons; }
+ set { _linkButtons = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to click
+ /// on linkable objects
+ /// </summary>
+ /// <seealso cref="LinkButtons" />
+ /// <seealso cref="LinkEvent"/>
+ // /// <seealso cref="ZedGraph.Web.IsImageMap"/>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( Keys.Alt ),
+ Description( "Specify modifier key for clicking on linkable objects" )]
+ public Keys LinkModifierKeys
+ {
+ get { return _linkModifierKeys; }
+ set { _linkModifierKeys = value; }
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.MasterPane"/> property for the control
+ /// </summary>
+ [Bindable( false ), Browsable( false ),
+ DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
+ public MasterPane MasterPane
+ {
+ get { lock ( this ) return _masterPane; }
+ set { lock ( this ) _masterPane = value; }
+ }
+
+ // Testing for Designer attribute
+ /*
+ Class1 _class1 = null;
+ [ Bindable( true ), Browsable( true ), Category( "Data" ), NotifyParentProperty( true ),
+ DesignerSerializationVisibility( DesignerSerializationVisibility.Content ),
+ Description( "My Class1 Test" )]
+ public Class1 Class1
+ {
+ get { if ( _class1 == null ) _class1 = new Class1(); return _class1; }
+ set { _class1 = value; }
+ }
+ */
+
+ /// <summary>
+ /// Gets or sets the <see cref="ZedGraph.GraphPane"/> property for the control
+ /// </summary>
+ /// <remarks>
+ /// <see cref="ZedGraphControl"/> actually uses a <see cref="MasterPane"/> object
+ /// to hold a list of <see cref="GraphPane"/> objects. This property really only
+ /// accesses the first <see cref="GraphPane"/> in the list. If there is more
+ /// than one <see cref="GraphPane"/>, use the <see cref="MasterPane"/>
+ /// indexer property to access any of the <see cref="GraphPane"/> objects.</remarks>
+ [
+ Bindable( false ), Browsable( false ),
+ DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )
+ ]
+ //[
+ // Bindable( true ), Browsable( true ), Category( "Data" ), NotifyParentProperty( true ),
+ // AttributeProvider( typeof( GraphPane ) ),
+ // Description("Access to the primary GraphPane object associated with this control")
+ //]
+ public GraphPane GraphPane
+ {
+ get
+ {
+ // Just return the first GraphPane in the list
+ lock ( this )
+ {
+ if ( _masterPane != null && _masterPane.PaneList.Count > 0 )
+ return _masterPane[0];
+ else
+ return null;
+ }
+ }
+
+ set
+ {
+ lock ( this )
+ {
+ //Clear the list, and replace it with the specified Graphpane
+ if ( _masterPane != null )
+ {
+ _masterPane.PaneList.Clear();
+ _masterPane.Add( value );
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if all drawing operations for this control
+ /// will be forced to operate in Anti-alias mode. Note that if this value is set to
+ /// "true", it overrides the setting for sub-objects. Otherwise, the sub-object settings
+ /// (such as <see cref="FontSpec.IsAntiAlias"/>)
+ /// will be honored.
+ /// </summary>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to force all objects to be draw in anti-alias mode" )]
+ public bool IsAntiAlias
+ {
+ get { return _masterPane.IsAntiAlias; }
+ set { _masterPane.IsAntiAlias = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not tooltips will be displayed
+ /// when the mouse hovers over data values.
+ /// </summary>
+ /// <remarks>The displayed values are taken from <see cref="PointPair.Tag"/>
+ /// if it is a <see cref="System.String"/> type, or <see cref="PointPairBase.ToString()"/>
+ /// otherwise (using the <see cref="PointValueFormat" /> as a format string).
+ /// Additionally, the user can custom format the values using the
+ /// <see cref="PointValueEvent" /> event. Note that <see cref="IsShowPointValues" />
+ /// may be overridden by <see cref="IsShowCursorValues" />.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to display tooltips when the mouse hovers over data points" )]
+ public bool IsShowPointValues
+ {
+ get { return _isShowPointValues; }
+ set { _isShowPointValues = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not tooltips will be displayed
+ /// showing the current scale values when the mouse is within the
+ /// <see cref="Chart.Rect" />.
+ /// </summary>
+ /// <remarks>The displayed values are taken from the current mouse position, and formatted
+ /// according to <see cref="PointValueFormat" /> and/or <see cref="PointDateFormat" />. If this
+ /// value is set to true, it overrides the <see cref="IsShowPointValues" /> setting.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to display tooltips showing the current mouse position within the Chart area" )]
+ public bool IsShowCursorValues
+ {
+ get { return _isShowCursorValues; }
+ set { _isShowCursorValues = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not editing of point data is allowed in
+ /// the horizontal direction.
+ /// </summary>
+ /// <remarks>
+ /// Editing is done by holding down the Alt key, and left-clicking on an individual point of
+ /// a given <see cref="CurveItem" /> to drag it to a new location. The Mouse and Key
+ /// combination for this mode are modifiable using <see cref="EditButtons" /> and
+ /// <see cref="EditModifierKeys" />.
+ /// </remarks>
+ /// <seealso cref="EditButtons" />
+ /// <seealso cref="EditModifierKeys" />
+ /// <seealso cref="IsEnableVEdit" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to allow horizontal editing by alt-left-click-drag" )]
+ public bool IsEnableHEdit
+ {
+ get { return _isEnableHEdit; }
+ set { _isEnableHEdit = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not editing of point data is allowed in
+ /// the vertical direction.
+ /// </summary>
+ /// <remarks>
+ /// Editing is done by holding down the Alt key, and left-clicking on an individual point of
+ /// a given <see cref="CurveItem" /> to drag it to a new location. The Mouse and Key
+ /// combination for this mode are modifiable using <see cref="EditButtons" /> and
+ /// <see cref="EditModifierKeys" />.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to allow vertical editing by alt-left-click-drag" )]
+ public bool IsEnableVEdit
+ {
+ get { return _isEnableVEdit; }
+ set { _isEnableVEdit = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not zooming is allowed for the control.
+ /// </summary>
+ /// <remarks>
+ /// Zooming is done by left-clicking inside the <see cref="Chart.Rect"/> to drag
+ /// out a rectangle, indicating the new scale ranges that will be part of the graph.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to allow horizontal and vertical zooming by left-click-drag" )]
+ public bool IsEnableZoom
+ {
+ set { _isEnableHZoom = value; _isEnableVZoom = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether or not zooming is allowed for the control in
+ /// the horizontal direction.
+ /// </summary>
+ /// <remarks>
+ /// Zooming is done by left-clicking inside the <see cref="Chart.Rect"/> to drag
+ /// out a rectangle, indicating the new scale ranges that will be part of the graph.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to allow horizontal zooming by left-click-drag" )]
+ public bool IsEnableHZoom
+ {
+ get { return _isEnableHZoom; }
+ set { _isEnableHZoom = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether or not zooming is allowed for the control in
+ /// the vertical direction.
+ /// </summary>
+ /// <remarks>
+ /// Zooming is done by left-clicking inside the <see cref="Chart.Rect"/> to drag
+ /// out a rectangle, indicating the new scale ranges that will be part of the graph.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to allow vertical zooming by left-click-drag" )]
+ public bool IsEnableVZoom
+ {
+ get { return _isEnableVZoom; }
+ set { _isEnableVZoom = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not zooming is allowed via the mouse wheel.
+ /// </summary>
+ /// <remarks>
+ /// Wheel zooming is done by rotating the mouse wheel.
+ /// Note that this property is used in combination with the <see cref="IsEnableHZoom"/> and
+ /// <see cref="IsEnableVZoom" /> properties to control zoom options.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to allow zooming with the mouse wheel" )]
+ public bool IsEnableWheelZoom
+ {
+ get { return _isEnableWheelZoom; }
+ set { _isEnableWheelZoom = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not panning is allowed for the control in
+ /// the horizontal direction.
+ /// </summary>
+ /// <remarks>
+ /// Panning is done by clicking the middle mouse button (or holding down the shift key
+ /// while clicking the left mouse button) inside the <see cref="Chart.Rect"/> and
+ /// dragging the mouse around to shift the scale ranges as desired.
+ /// </remarks>
+ /// <seealso cref="IsEnableVPan"/>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to allow horizontal panning by middle-mouse-drag or shift-left-drag" )]
+ public bool IsEnableHPan
+ {
+ get { return _isEnableHPan; }
+ set { _isEnableHPan = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not panning is allowed for the control in
+ /// the vertical direction.
+ /// </summary>
+ /// <remarks>
+ /// Panning is done by clicking the middle mouse button (or holding down the shift key
+ /// while clicking the left mouse button) inside the <see cref="Chart.Rect"/> and
+ /// dragging the mouse around to shift the scale ranges as desired.
+ /// </remarks>
+ /// <seealso cref="IsEnableHPan"/>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to allow vertical panning by middle-mouse-drag or shift-left-drag" )]
+ public bool IsEnableVPan
+ {
+ get { return _isEnableVPan; }
+ set { _isEnableVPan = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the context menu will be available.
+ /// </summary>
+ /// <remarks>The context menu is a menu that appears when you right-click on the
+ /// <see cref="ZedGraphControl"/>. It provides options for Zoom, Pan, AutoScale, Clipboard
+ /// Copy, and toggle <see cref="IsShowPointValues"/>.
+ /// </remarks>
+ /// <value>true to allow the context menu, false to disable it</value>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to enable the right mouse button context menu" )]
+ public bool IsShowContextMenu
+ {
+ get { return _isShowContextMenu; }
+ set { _isShowContextMenu = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not a message box will be shown
+ /// in response to a context menu "Copy" command.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if this property is set to false, the user will receive no
+ /// indicative feedback in response to a Copy action.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to show a message box after a 'Copy' context menu action completes" )]
+ public bool IsShowCopyMessage
+ {
+ get { return _isShowCopyMessage; }
+ set { _isShowCopyMessage = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="SaveFileDialog" /> instance that will be used
+ /// by the "Save As..." context menu item.
+ /// </summary>
+ /// <remarks>
+ /// This provides the opportunity to modify the dialog, such as setting the
+ /// <see cref="FileDialog.InitialDirectory" /> property.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "Provides access to the SaveFileDialog for the 'Save As' menu item" )]
+ public SaveFileDialog SaveFileDialog
+ {
+ get { return _saveFileDialog; }
+ set { _saveFileDialog = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the visible aspect ratio of the
+ /// <see cref="MasterPane" /> <see cref="PaneBase.Rect" /> will be preserved
+ /// when printing this <see cref="ZedGraphControl" />.
+ /// </summary>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to preserve the displayed aspect ratio when printing" )]
+ public bool IsPrintKeepAspectRatio
+ {
+ get { return _isPrintKeepAspectRatio; }
+ set { _isPrintKeepAspectRatio = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not the <see cref="MasterPane" />
+ /// <see cref="PaneBase.Rect" /> dimensions will be expanded to fill the
+ /// available space when printing this <see cref="ZedGraphControl" />.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="IsPrintKeepAspectRatio" /> is also true, then the <see cref="MasterPane" />
+ /// <see cref="PaneBase.Rect" /> dimensions will be expanded to fit as large
+ /// a space as possible while still honoring the visible aspect ratio.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to resize to fill the page when printing" )]
+ public bool IsPrintFillPage
+ {
+ get { return _isPrintFillPage; }
+ set { _isPrintFillPage = value; }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines whether the settings of
+ /// <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and <see cref="PaneBase.IsPenWidthScaled" />
+ /// will be overridden to true during printing operations.
+ /// </summary>
+ /// <remarks>
+ /// Printing involves pixel maps that are typically of a dramatically different dimension
+ /// than on-screen pixel maps. Therefore, it becomes more important to scale the fonts and
+ /// lines to give a printed image that looks like what is shown on-screen. The default
+ /// setting for <see cref="ZedGraph.PaneBase.IsFontsScaled" /> is true, but the default
+ /// setting for <see cref="PaneBase.IsPenWidthScaled" /> is false.
+ /// </remarks>
+ /// <value>
+ /// A value of true will cause both <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and
+ /// <see cref="PaneBase.IsPenWidthScaled" /> to be temporarily set to true during
+ /// printing operations.
+ /// </value>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( true ),
+ Description( "true to force font and pen width scaling when printing" )]
+ public bool IsPrintScaleAll
+ {
+ get { return _isPrintScaleAll; }
+ set { _isPrintScaleAll = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that controls whether or not the axis value range for the scroll
+ /// bars will be set automatically.
+ /// </summary>
+ /// <remarks>
+ /// If this value is set to true, then the range of the scroll bars will be set automatically
+ /// to the actual range of the data as returned by <see cref="CurveList.GetRange" /> at the
+ /// time that <see cref="AxisChange" /> was last called. Note that a value of true
+ /// can override any setting of <see cref="ScrollMinX" />, <see cref="ScrollMaxX" />,
+ /// <see cref="ScrollMinY" />, <see cref="ScrollMaxY" />,
+ /// <see cref="ScrollMinY2" />, and <see cref="ScrollMaxY2" />. Note also that you must
+ /// call <see cref="AxisChange" /> from the <see cref="ZedGraphControl" /> for this to
+ /// work properly (e.g., don't call it directly from the <see cref="GraphPane" />.
+ /// Alternatively, you can call <see cref="SetScrollRangeFromData" /> at anytime to set
+ /// the scroll bar range.<br />
+ /// <b>In most cases, you will probably want to disable
+ /// <see cref="ZedGraph.GraphPane.IsBoundedRanges" /> before activating this option.</b>
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to automatically set the scroll bar range to the actual data range" )]
+ public bool IsAutoScrollRange
+ {
+ get { return _isAutoScrollRange; }
+ set { _isAutoScrollRange = value; }
+ }
+
+ /// <summary>
+ /// Set a "grace" value that leaves a buffer area around the data when
+ /// <see cref="IsAutoScrollRange" /> is true.
+ /// </summary>
+ /// <remarks>
+ /// This value represents a fraction of the total range around each axis. For example, if the
+ /// axis ranges from 0 to 100, then a 0.05 value for ScrollGrace would set the scroll range
+ /// to -5 to 105.
+ /// </remarks>
+ public double ScrollGrace
+ {
+ get { return _scrollGrace; }
+ set { _scrollGrace = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the horizontal scroll bar will be visible.
+ /// </summary>
+ /// <remarks>This scroll bar allows the display to be scrolled in the horizontal direction.
+ /// Another option is display panning, in which the user can move the display around by
+ /// clicking directly on it and dragging (see <see cref="IsEnableHPan"/> and <see cref="IsEnableVPan"/>).
+ /// You can control the available range of scrolling with the <see cref="ScrollMinX"/> and
+ /// <see cref="ScrollMaxX"/> properties. Note that the scroll range can be set automatically by
+ /// <see cref="IsAutoScrollRange" />.<br />
+ /// <b>In most cases, you will probably want to disable
+ /// <see cref="ZedGraph.GraphPane.IsBoundedRanges" /> before activating this option.</b>
+ /// </remarks>
+ /// <value>A boolean value. true to display a horizontal scrollbar, false otherwise.</value>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to display the horizontal scroll bar" )]
+ public bool IsShowHScrollBar
+ {
+ get { return _isShowHScrollBar; }
+ set { _isShowHScrollBar = value; ZedGraphControl_ReSize( this, new EventArgs() ); }
+ }
+ /// <summary>
+ /// Gets or sets a value that determines if the vertical scroll bar will be visible.
+ /// </summary>
+ /// <remarks>This scroll bar allows the display to be scrolled in the vertical direction.
+ /// Another option is display panning, in which the user can move the display around by
+ /// clicking directly on it and dragging (see <see cref="IsEnableHPan"/> and <see cref="IsEnableVPan"/>).
+ /// You can control the available range of scrolling with the <see cref="ScrollMinY"/> and
+ /// <see cref="ScrollMaxY"/> properties.
+ /// Note that the vertical scroll bar only affects the <see cref="YAxis"/>; it has no impact on
+ /// the <see cref="Y2Axis"/>. The panning options affect both the <see cref="YAxis"/> and
+ /// <see cref="Y2Axis"/>. Note also that the scroll range can be set automatically by
+ /// <see cref="IsAutoScrollRange" />.<br />
+ /// <b>In most cases, you will probably want to disable
+ /// <see cref="ZedGraph.GraphPane.IsBoundedRanges" /> before activating this option.</b>
+ /// </remarks>
+ /// <value>A boolean value. true to display a vertical scrollbar, false otherwise.</value>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to display the vertical scroll bar" )]
+ public bool IsShowVScrollBar
+ {
+ get { return _isShowVScrollBar; }
+ set { _isShowVScrollBar = value; ZedGraphControl_ReSize( this, new EventArgs() ); }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the <see cref="XAxis" /> <see cref="Scale" />
+ /// ranges for all <see cref="GraphPane" /> objects in the <see cref="MasterPane" /> will
+ /// be forced to match.
+ /// </summary>
+ /// <remarks>
+ /// If set to true (default is false), then all of the <see cref="GraphPane" /> objects
+ /// in the <see cref="MasterPane" /> associated with this <see cref="ZedGraphControl" />
+ /// will be forced to have matching scale ranges for the x axis. That is, zoom, pan,
+ /// and scroll operations will result in zoom/pan/scroll for all graphpanes simultaneously.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to force the X axis ranges for all GraphPanes to match" )]
+ public bool IsSynchronizeXAxes
+ {
+ get { return _isSynchronizeXAxes; }
+ set
+ {
+ if ( _isSynchronizeXAxes != value )
+ ZoomStatePurge();
+ _isSynchronizeXAxes = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the <see cref="YAxis" /> <see cref="Scale" />
+ /// ranges for all <see cref="GraphPane" /> objects in the <see cref="MasterPane" /> will
+ /// be forced to match.
+ /// </summary>
+ /// <remarks>
+ /// If set to true (default is false), then all of the <see cref="GraphPane" /> objects
+ /// in the <see cref="MasterPane" /> associated with this <see cref="ZedGraphControl" />
+ /// will be forced to have matching scale ranges for the y axis. That is, zoom, pan,
+ /// and scroll operations will result in zoom/pan/scroll for all graphpanes simultaneously.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to force the Y axis ranges for all GraphPanes to match" )]
+ public bool IsSynchronizeYAxes
+ {
+ get { return _isSynchronizeYAxes; }
+ set
+ {
+ if ( _isSynchronizeYAxes != value )
+ ZoomStatePurge();
+ _isSynchronizeYAxes = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines if the vertical scroll bar will affect the Y2 axis.
+ /// </summary>
+ /// <remarks>
+ /// The vertical scroll bar is automatically associated with the Y axis. With this value, you
+ /// can choose to include or exclude the Y2 axis with the scrolling. Note that the Y2 axis
+ /// scrolling is handled as a secondary. The vertical scroll bar position always reflects
+ /// the status of the Y axis. This can cause the Y2 axis to "jump" when first scrolled if
+ /// the <see cref="ScrollMinY2" /> and <see cref="ScrollMaxY2" /> values are not set to the
+ /// same proportions as <see cref="ScrollMinY" /> and <see cref="ScrollMaxY" /> with respect
+ /// to the actual <see cref="Scale.Min"/> and <see cref="Scale.Max" />. Also note that
+ /// this property is actually just an alias to the <see cref="ScrollRange.IsScrollable" />
+ /// property of the first element of <see cref="YScrollRangeList" />.
+ /// </remarks>
+ /// <seealso cref="IsShowVScrollBar"/>
+ /// <seealso cref="ScrollMinY2"/>
+ /// <seealso cref="ScrollMaxY2"/>
+ /// <seealso cref="YScrollRangeList" />
+ /// <seealso cref="Y2ScrollRangeList" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to scroll the Y2 axis along with the Y axis" )]
+ public bool IsScrollY2
+ {
+ get
+ {
+ if ( _y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0 )
+ return _y2ScrollRangeList[0].IsScrollable;
+ else
+ return false;
+ }
+ set
+ {
+ if ( _y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0 )
+ {
+ ScrollRange tmp = _y2ScrollRangeList[0];
+ tmp.IsScrollable = value;
+ _y2ScrollRangeList[0] = tmp;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Access the <see cref="ScrollRangeList" /> for the Y axes.
+ /// </summary>
+ /// <remarks>
+ /// This list maintains the user scale ranges for the scroll bars for each axis
+ /// in the <see cref="ZedGraph.GraphPane.YAxisList" />. Each ordinal location in
+ /// <see cref="YScrollRangeList" /> corresponds to an equivalent ordinal location
+ /// in <see cref="ZedGraph.GraphPane.YAxisList" />.
+ /// </remarks>
+ /// <seealso cref="ScrollMinY" />
+ /// <seealso cref="ScrollMaxY" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true )]
+ [Description( "Sets the manual scroll bar ranges for the collection of Y axes" )]
+ public ScrollRangeList YScrollRangeList
+ {
+ get { return _yScrollRangeList; }
+ }
+
+ /// <summary>
+ /// Access the <see cref="ScrollRangeList" /> for the Y2 axes.
+ /// </summary>
+ /// <remarks>
+ /// This list maintains the user scale ranges for the scroll bars for each axis
+ /// in the <see cref="ZedGraph.GraphPane.Y2AxisList" />. Each ordinal location in
+ /// <see cref="Y2ScrollRangeList" /> corresponds to an equivalent ordinal location
+ /// in <see cref="ZedGraph.GraphPane.Y2AxisList" />.
+ /// </remarks>
+ /// <seealso cref="ScrollMinY2" />
+ /// <seealso cref="ScrollMaxY2" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true )]
+ [Description( "Sets the manual scroll bar ranges for the collection of Y2 axes" )]
+ public ScrollRangeList Y2ScrollRangeList
+ {
+ get { return _y2ScrollRangeList; }
+ }
+
+ /// <summary>
+ /// The minimum value for the X axis scroll range.
+ /// </summary>
+ /// <remarks>
+ /// Effectively, the minimum endpoint of the scroll range will cause the
+ /// <see cref="Scale.Min"/> value to be set to <see cref="ScrollMinX"/>. Note that this
+ /// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableHPan"/>)
+ /// is not affected by this value. Note that this value can be overridden by
+ /// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />.
+ /// </remarks>
+ /// <value>A double value indicating the minimum axis value</value>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0 ),
+ Description( "Sets the manual scroll minimum value for the X axis" )]
+ public double ScrollMinX
+ {
+ get { return _xScrollRange.Min; }
+ set { _xScrollRange.Min = value; }
+ }
+ /// <summary>
+ /// The maximum value for the X axis scroll range.
+ /// </summary>
+ /// <remarks>
+ /// Effectively, the maximum endpoint of the scroll range will cause the
+ /// <see cref="Scale.Max"/> value to be set to <see cref="ScrollMaxX"/>. Note that this
+ /// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableHPan"/>)
+ /// is not affected by this value. Note that this value can be overridden by
+ /// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />.
+ /// </remarks>
+ /// <value>A double value indicating the maximum axis value</value>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0 ),
+ Description( "Sets the manual scroll maximum value for the X axis" )]
+ public double ScrollMaxX
+ {
+ get { return _xScrollRange.Max; }
+ set { _xScrollRange.Max = value; }
+ }
+ /// <summary>
+ /// The minimum value for the Y axis scroll range.
+ /// </summary>
+ /// <remarks>
+ /// Effectively, the minimum endpoint of the scroll range will cause the
+ /// <see cref="Scale.Min"/> value to be set to <see cref="ScrollMinY"/>. Note that this
+ /// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
+ /// is not affected by this value. Note that this value can be overridden by
+ /// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
+ /// this property is actually just an alias to the <see cref="ScrollRange.Min" />
+ /// property of the first element of <see cref="YScrollRangeList" />.
+ /// </remarks>
+ /// <value>A double value indicating the minimum axis value</value>
+ /// <seealso cref="YScrollRangeList" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0 ),
+ Description( "Sets the manual scroll minimum value for the Y axis" )]
+ public double ScrollMinY
+ {
+ get
+ {
+ if ( _yScrollRangeList != null && _yScrollRangeList.Count > 0 )
+ return _yScrollRangeList[0].Min;
+ else
+ return double.NaN;
+ }
+ set
+ {
+ if ( _yScrollRangeList != null && _yScrollRangeList.Count > 0 )
+ {
+ ScrollRange tmp = _yScrollRangeList[0];
+ tmp.Min = value;
+ _yScrollRangeList[0] = tmp;
+ }
+ }
+ }
+ /// <summary>
+ /// The maximum value for the Y axis scroll range.
+ /// </summary>
+ /// <remarks>
+ /// Effectively, the maximum endpoint of the scroll range will cause the
+ /// <see cref="Scale.Max"/> value to be set to <see cref="ScrollMaxY"/>. Note that this
+ /// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
+ /// is not affected by this value. Note that this value can be overridden by
+ /// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
+ /// this property is actually just an alias to the <see cref="ScrollRange.Max" />
+ /// property of the first element of <see cref="YScrollRangeList" />.
+ /// </remarks>
+ /// <value>A double value indicating the maximum axis value</value>
+ /// <seealso cref="YScrollRangeList" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0 ),
+ Description( "Sets the manual scroll maximum value for the Y axis" )]
+ public double ScrollMaxY
+ {
+ get
+ {
+ if ( _yScrollRangeList != null && _yScrollRangeList.Count > 0 )
+ return _yScrollRangeList[0].Max;
+ else
+ return double.NaN;
+ }
+ set
+ {
+ if ( _yScrollRangeList != null && _yScrollRangeList.Count > 0 )
+ {
+ ScrollRange tmp = _yScrollRangeList[0];
+ tmp.Max = value;
+ _yScrollRangeList[0] = tmp;
+ }
+ }
+ }
+ /// <summary>
+ /// The minimum value for the Y2 axis scroll range.
+ /// </summary>
+ /// <remarks>
+ /// Effectively, the minimum endpoint of the scroll range will cause the
+ /// <see cref="Scale.Min"/> value to be set to <see cref="ScrollMinY2"/>. Note that this
+ /// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
+ /// is not affected by this value. Note that this value can be overridden by
+ /// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
+ /// this property is actually just an alias to the <see cref="ScrollRange.Min" />
+ /// property of the first element of <see cref="Y2ScrollRangeList" />.
+ /// </remarks>
+ /// <value>A double value indicating the minimum axis value</value>
+ /// <seealso cref="Y2ScrollRangeList" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0 ),
+ Description( "Sets the manual scroll minimum value for the Y2 axis" )]
+ public double ScrollMinY2
+ {
+ get
+ {
+ if ( _y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0 )
+ return _y2ScrollRangeList[0].Min;
+ else
+ return double.NaN;
+ }
+ set
+ {
+ if ( _y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0 )
+ {
+ ScrollRange tmp = _y2ScrollRangeList[0];
+ tmp.Min = value;
+ _y2ScrollRangeList[0] = tmp;
+ }
+ }
+ }
+ /// <summary>
+ /// The maximum value for the Y2 axis scroll range.
+ /// </summary>
+ /// <remarks>
+ /// Effectively, the maximum endpoint of the scroll range will cause the
+ /// <see cref="Scale.Max"/> value to be set to <see cref="ScrollMaxY2"/>. Note that this
+ /// value applies only to the scroll bar settings. Axis panning (see <see cref="IsEnableVPan"/>)
+ /// is not affected by this value. Note that this value can be overridden by
+ /// <see cref="IsAutoScrollRange" /> and <see cref="SetScrollRangeFromData" />. Also note that
+ /// this property is actually just an alias to the <see cref="ScrollRange.Max" />
+ /// property of the first element of <see cref="Y2ScrollRangeList" />.
+ /// </remarks>
+ /// <value>A double value indicating the maximum axis value</value>
+ /// <seealso cref="Y2ScrollRangeList" />
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0 ),
+ Description( "Sets the manual scroll maximum value for the Y2 axis" )]
+ public double ScrollMaxY2
+ {
+ get
+ {
+ if ( _y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0 )
+ return _y2ScrollRangeList[0].Max;
+ else
+ return double.NaN;
+ }
+ set
+ {
+ if ( _y2ScrollRangeList != null && _y2ScrollRangeList.Count > 0 )
+ {
+ ScrollRange tmp = _y2ScrollRangeList[0];
+ tmp.Max = value;
+ _y2ScrollRangeList[0] = tmp;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns true if the user is currently scrolling via the scrollbar, or
+ /// false if no scrolling is taking place.
+ /// </summary>
+ /// <remarks>
+ /// This method just tests ScrollBar.Capture to see if the
+ /// mouse has been captured by the scroll bar. If so, scrolling is active.
+ /// </remarks>
+ public Boolean IsScrolling
+ {
+ get
+ {
+ if ( hScrollBar1 != null && vScrollBar1 != null )
+ return hScrollBar1.Capture || vScrollBar1.Capture;
+ else
+ return false;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets or sets the format for displaying tooltip values.
+ /// This format is passed to <see cref="PointPairBase.ToString(string)"/>.
+ /// </summary>
+ /// <remarks>
+ /// Use the <see cref="System.Globalization.NumberFormatInfo" /> type
+ /// to determine the format strings.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( PointPair.DefaultFormat ),
+ Description( "Sets the numeric display format string for the point value tooltips" )]
+ public string PointValueFormat
+ {
+ get { return _pointValueFormat; }
+ set { _pointValueFormat = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the format for displaying tooltip values.
+ /// This format is passed to <see cref="XDate.ToString(string)"/>.
+ /// </summary>
+ /// <remarks>
+ /// Use the <see cref="System.Globalization.DateTimeFormatInfo" /> type
+ /// to determine the format strings.
+ /// </remarks>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( XDate.DefaultFormatStr ),
+ Description( "Sets the date display format for the point value tooltips" )]
+ public string PointDateFormat
+ {
+ get { return _pointDateFormat; }
+ set { _pointDateFormat = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the step size fraction for zooming with the mouse wheel.
+ /// A value of 0.1 will result in a 10% zoom step for each mouse wheel movement.
+ /// </summary>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( 0.1 ),
+ Description( "Sets the step size fraction for zooming with the mouse wheel" )]
+ public double ZoomStepFraction
+ {
+ get { return _zoomStepFraction; }
+ set { _zoomStepFraction = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a boolean value that determines if zooming with the wheel mouse
+ /// is centered on the mouse location, or centered on the existing graph.
+ /// </summary>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to center the mouse wheel zoom at the current mouse location" )]
+ public bool IsZoomOnMouseCenter
+ {
+ get { return _isZoomOnMouseCenter; }
+ set { _isZoomOnMouseCenter = value; }
+ }
+
+ /// <summary>
+ /// Gets the graph pane's current image.
+ /// <seealso cref="Bitmap"/>
+ /// </summary>
+ /// <exception cref="ZedGraphException">
+ /// When the control has been disposed before this call.
+ /// </exception>
+ [Bindable( false ), Browsable( false ),
+ DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
+ public Image GetImage()
+ {
+ lock ( this )
+ {
+ if ( BeenDisposed || _masterPane == null || _masterPane[0] == null )
+ throw new ZedGraphException( "The control has been disposed" );
+
+ return _masterPane.GetImage();
+ }
+ }
+
+ /// <summary>
+ /// This checks if the control has been disposed. This is synonymous with
+ /// the graph pane having been nulled or disposed. Therefore this is the
+ /// same as <c>ZedGraphControl.GraphPane == null</c>.
+ /// </summary>
+ [Bindable( false ), Browsable( false ),
+ DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
+ public bool BeenDisposed
+ {
+ get
+ {
+ lock ( this ) return _masterPane == null;
+ }
+ }
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Readonly property that gets the list of selected CurveItems
+ /// </summary>
+ public Selection Selection
+ {
+ get { return _selection; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that determines whether or not selection is allowed for the control.
+ /// </summary>
+ [Bindable( true ), Category( "Display" ), NotifyParentProperty( true ),
+ DefaultValue( false ),
+ Description( "true to allow selecting Curves" )]
+ public bool IsEnableSelection
+ {
+ get { return _isEnableSelection; }
+ set
+ {
+ _isEnableSelection = value;
+
+ /*
+ if ( value )
+ {
+ this.Cursor = Cursors.Default;
+ this.IsEnableZoom = false;
+ }
+ else
+ {
+ this.Cursor = Cursors.Cross;
+ this.IsEnableZoom = true;
+ }
+ */
+ }
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/ZedGraph/ZedGraphControl.ScrollBars.cs b/ZedGraph/ZedGraphControl.ScrollBars.cs
new file mode 100644
index 0000000..a2bb2ae
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.ScrollBars.cs
@@ -0,0 +1,395 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2007 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace ZedGraph
+{
+ partial class ZedGraphControl
+ {
+
+ #region ScrollBars
+
+ private void vScrollBar1_Scroll( object sender, ScrollEventArgs e )
+ {
+ if ( this.GraphPane != null )
+ {
+ if ( ( e.Type != ScrollEventType.ThumbPosition &&
+ e.Type != ScrollEventType.ThumbTrack ) ||
+ ( e.Type == ScrollEventType.ThumbTrack &&
+ _zoomState == null ) )
+ {
+ ZoomStateSave( this.GraphPane, ZoomState.StateType.Scroll );
+ }
+ for ( int i = 0; i < this.GraphPane.YAxisList.Count; i++ )
+ {
+ ScrollRange scroll = _yScrollRangeList[i];
+ if ( scroll.IsScrollable )
+ {
+ Axis axis = this.GraphPane.YAxisList[i];
+ HandleScroll( axis, e.NewValue, scroll.Min, scroll.Max, vScrollBar1.LargeChange,
+ !axis.Scale.IsReverse );
+ }
+ }
+
+ for ( int i = 0; i < this.GraphPane.Y2AxisList.Count; i++ )
+ {
+ ScrollRange scroll = _y2ScrollRangeList[i];
+ if ( scroll.IsScrollable )
+ {
+ Axis axis = this.GraphPane.Y2AxisList[i];
+ HandleScroll( axis, e.NewValue, scroll.Min, scroll.Max, vScrollBar1.LargeChange,
+ !axis.Scale.IsReverse );
+ }
+ }
+
+ ApplyToAllPanes( this.GraphPane );
+
+ ProcessEventStuff( vScrollBar1, e );
+ }
+ }
+
+ private void ApplyToAllPanes( GraphPane primaryPane )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ if ( pane != primaryPane )
+ {
+ if ( _isSynchronizeXAxes )
+ Synchronize( primaryPane.XAxis, pane.XAxis );
+ if ( _isSynchronizeYAxes )
+ Synchronize( primaryPane.YAxis, pane.YAxis );
+ }
+ }
+ }
+
+ private void Synchronize( Axis source, Axis dest )
+ {
+ dest._scale._min = source._scale._min;
+ dest._scale._max = source._scale._max;
+ dest._scale._majorStep = source._scale._majorStep;
+ dest._scale._minorStep = source._scale._minorStep;
+ dest._scale._minAuto = source._scale._minAuto;
+ dest._scale._maxAuto = source._scale._maxAuto;
+ dest._scale._majorStepAuto = source._scale._majorStepAuto;
+ dest._scale._minorStepAuto = source._scale._minorStepAuto;
+ }
+
+ private void hScrollBar1_Scroll( object sender, ScrollEventArgs e )
+ {
+ if ( this.GraphPane != null )
+ {
+ if ( ( e.Type != ScrollEventType.ThumbPosition &&
+ e.Type != ScrollEventType.ThumbTrack ) ||
+ ( e.Type == ScrollEventType.ThumbTrack &&
+ _zoomState == null ) )
+ ZoomStateSave( this.GraphPane, ZoomState.StateType.Scroll );
+
+ HandleScroll( this.GraphPane.XAxis, e.NewValue, _xScrollRange.Min, _xScrollRange.Max,
+ hScrollBar1.LargeChange, this.GraphPane.XAxis.Scale.IsReverse );
+
+ ApplyToAllPanes( this.GraphPane );
+
+ ProcessEventStuff( hScrollBar1, e );
+ }
+ }
+
+ private void ProcessEventStuff( ScrollBar scrollBar, ScrollEventArgs e )
+ {
+ if ( e.Type == ScrollEventType.ThumbTrack )
+ {
+ if ( this.ScrollProgressEvent != null )
+ this.ScrollProgressEvent( this, hScrollBar1, _zoomState,
+ new ZoomState( this.GraphPane, ZoomState.StateType.Scroll ) );
+ }
+ else // if ( e.Type == ScrollEventType.ThumbPosition )
+ {
+ if ( _zoomState != null && _zoomState.IsChanged( this.GraphPane ) )
+ {
+ //this.GraphPane.ZoomStack.Push( _zoomState );
+ ZoomStatePush( this.GraphPane );
+
+ // Provide Callback to notify the user of pan events
+ if ( this.ScrollDoneEvent != null )
+ this.ScrollDoneEvent( this, hScrollBar1, _zoomState,
+ new ZoomState( this.GraphPane, ZoomState.StateType.Scroll ) );
+
+ _zoomState = null;
+ }
+ }
+
+ if ( this.ScrollEvent != null )
+ this.ScrollEvent( scrollBar, e );
+ }
+/*
+ /// <summary>
+ /// Use the MouseCaptureChanged as an indicator for the start and end of a scrolling operation
+ /// </summary>
+ private void ScrollBarMouseCaptureChanged( object sender, EventArgs e )
+ {
+ return;
+
+ ScrollBar scrollBar = sender as ScrollBar;
+ if ( scrollBar != null )
+ {
+ // If this is the start of a new scroll, then Capture will be true
+ if ( scrollBar.Capture )
+ {
+ // save the original zoomstate
+ //_zoomState = new ZoomState( this.GraphPane, ZoomState.StateType.Scroll );
+ ZoomStateSave( this.GraphPane, ZoomState.StateType.Scroll );
+ }
+ else
+ {
+ // push the prior saved zoomstate, since the scale ranges have already been changed on
+ // the fly during the scrolling operation
+ if ( _zoomState != null && _zoomState.IsChanged( this.GraphPane ) )
+ {
+ //this.GraphPane.ZoomStack.Push( _zoomState );
+ ZoomStatePush( this.GraphPane );
+
+ // Provide Callback to notify the user of pan events
+ if ( this.ScrollDoneEvent != null )
+ this.ScrollDoneEvent( this, scrollBar, _zoomState,
+ new ZoomState( this.GraphPane, ZoomState.StateType.Scroll ) );
+
+ _zoomState = null;
+ }
+ }
+ }
+ }
+*/
+
+ private void HandleScroll( Axis axis, int newValue, double scrollMin, double scrollMax,
+ int largeChange, bool reverse )
+ {
+ if ( axis != null )
+ {
+ if ( scrollMin > axis._scale._min )
+ scrollMin = axis._scale._min;
+ if ( scrollMax < axis._scale._max )
+ scrollMax = axis._scale._max;
+
+ int span = _ScrollControlSpan - largeChange;
+ if ( span <= 0 )
+ return;
+
+ if ( reverse )
+ newValue = span - newValue;
+
+ Scale scale = axis._scale;
+
+ double delta = scale._maxLinearized - scale._minLinearized;
+ double scrollMin2 = scale.Linearize( scrollMax ) - delta;
+ scrollMin = scale.Linearize( scrollMin );
+ //scrollMax = scale.Linearize( scrollMax );
+ double val = scrollMin + (double)newValue / (double)span *
+ ( scrollMin2 - scrollMin );
+ scale._minLinearized = val;
+ scale._maxLinearized = val + delta;
+ /*
+ if ( axis.Scale.IsLog )
+ {
+ double ratio = axis._scale._max / axis._scale._min;
+ double scrollMin2 = scrollMax / ratio;
+
+ double val = scrollMin * Math.Exp( (double)newValue / (double)span *
+ ( Math.Log( scrollMin2 ) - Math.Log( scrollMin ) ) );
+ axis._scale._min = val;
+ axis._scale._max = val * ratio;
+ }
+ else
+ {
+ double delta = axis._scale._max - axis._scale._min;
+ double scrollMin2 = scrollMax - delta;
+
+ double val = scrollMin + (double)newValue / (double)span *
+ ( scrollMin2 - scrollMin );
+ axis._scale._min = val;
+ axis._scale._max = val + delta;
+ }
+ */
+ this.Invalidate();
+ }
+ }
+
+ /// <summary>
+ /// Sets the value of the scroll range properties (see <see cref="ScrollMinX" />,
+ /// <see cref="ScrollMaxX" />, <see cref="YScrollRangeList" />, and
+ /// <see cref="Y2ScrollRangeList" /> based on the actual range of the data for
+ /// each corresponding <see cref="Axis" />.
+ /// </summary>
+ /// <remarks>
+ /// This method is called automatically by <see cref="AxisChange" /> if
+ /// <see cref="IsAutoScrollRange" />
+ /// is true. Note that this will not be called if you call AxisChange directly from the
+ /// <see cref="GraphPane" />. For example, zedGraphControl1.AxisChange() works properly, but
+ /// zedGraphControl1.GraphPane.AxisChange() does not.</remarks>
+ public void SetScrollRangeFromData()
+ {
+ if ( this.GraphPane != null )
+ {
+ double grace = CalcScrollGrace( this.GraphPane.XAxis.Scale._rangeMin,
+ this.GraphPane.XAxis.Scale._rangeMax );
+
+ _xScrollRange.Min = this.GraphPane.XAxis.Scale._rangeMin - grace;
+ _xScrollRange.Max = this.GraphPane.XAxis.Scale._rangeMax + grace;
+ _xScrollRange.IsScrollable = true;
+
+ for ( int i = 0; i < this.GraphPane.YAxisList.Count; i++ )
+ {
+ Axis axis = this.GraphPane.YAxisList[i];
+ grace = CalcScrollGrace( axis.Scale._rangeMin, axis.Scale._rangeMax );
+ ScrollRange range = new ScrollRange( axis.Scale._rangeMin - grace,
+ axis.Scale._rangeMax + grace, _yScrollRangeList[i].IsScrollable );
+
+ if ( i >= _yScrollRangeList.Count )
+ _yScrollRangeList.Add( range );
+ else
+ _yScrollRangeList[i] = range;
+ }
+
+ for ( int i = 0; i < this.GraphPane.Y2AxisList.Count; i++ )
+ {
+ Axis axis = this.GraphPane.Y2AxisList[i];
+ grace = CalcScrollGrace( axis.Scale._rangeMin, axis.Scale._rangeMax );
+ ScrollRange range = new ScrollRange( axis.Scale._rangeMin - grace,
+ axis.Scale._rangeMax + grace, _y2ScrollRangeList[i].IsScrollable );
+
+ if ( i >= _y2ScrollRangeList.Count )
+ _y2ScrollRangeList.Add( range );
+ else
+ _y2ScrollRangeList[i] = range;
+ }
+
+ //this.GraphPane.CurveList.GetRange( out scrollMinX, out scrollMaxX,
+ // out scrollMinY, out scrollMaxY, out scrollMinY2, out scrollMaxY2, false, false,
+ // this.GraphPane );
+ }
+ }
+
+ private double CalcScrollGrace( double min, double max )
+ {
+ if ( Math.Abs( max - min ) < 1e-30 )
+ {
+ if ( Math.Abs( max ) < 1e-30 )
+ return _scrollGrace;
+ else
+ return max * _scrollGrace;
+ }
+ else
+ return ( max - min ) * _scrollGrace;
+ }
+
+ private void SetScroll( ScrollBar scrollBar, Axis axis, double scrollMin, double scrollMax )
+ {
+ if ( scrollBar != null && axis != null )
+ {
+ scrollBar.Minimum = 0;
+ scrollBar.Maximum = _ScrollControlSpan - 1;
+
+ if ( scrollMin > axis._scale._min )
+ scrollMin = axis._scale._min;
+ if ( scrollMax < axis._scale._max )
+ scrollMax = axis._scale._max;
+
+ int val = 0;
+
+ Scale scale = axis._scale;
+ double minLinearized = scale._minLinearized;
+ double maxLinearized = scale._maxLinearized;
+ scrollMin = scale.Linearize( scrollMin );
+ scrollMax = scale.Linearize( scrollMax );
+
+ double scrollMin2 = scrollMax - ( maxLinearized - minLinearized );
+ /*
+ if ( axis.Scale.IsLog )
+ scrollMin2 = scrollMax / ( axis._scale._max / axis._scale._min );
+ else
+ scrollMin2 = scrollMax - ( axis._scale._max - axis._scale._min );
+ */
+ if ( scrollMin >= scrollMin2 )
+ {
+ //scrollBar.Visible = false;
+ scrollBar.Enabled = false;
+ scrollBar.Value = 0;
+ }
+ else
+ {
+ double ratio = ( maxLinearized - minLinearized ) / ( scrollMax - scrollMin );
+
+ /*
+ if ( axis.Scale.IsLog )
+ ratio = ( Math.Log( axis._scale._max ) - Math.Log( axis._scale._min ) ) /
+ ( Math.Log( scrollMax ) - Math.Log( scrollMin ) );
+ else
+ ratio = ( axis._scale._max - axis._scale._min ) / ( scrollMax - scrollMin );
+ */
+
+ int largeChange = (int)( ratio * _ScrollControlSpan + 0.5 );
+ if ( largeChange < 1 )
+ largeChange = 1;
+ scrollBar.LargeChange = largeChange;
+
+ int smallChange = largeChange / _ScrollSmallRatio;
+ if ( smallChange < 1 )
+ smallChange = 1;
+ scrollBar.SmallChange = smallChange;
+
+ int span = _ScrollControlSpan - largeChange;
+
+ val = (int)( ( minLinearized - scrollMin ) / ( scrollMin2 - scrollMin ) *
+ span + 0.5 );
+ /*
+ if ( axis.Scale.IsLog )
+ val = (int)( ( Math.Log( axis._scale._min ) - Math.Log( scrollMin ) ) /
+ ( Math.Log( scrollMin2 ) - Math.Log( scrollMin ) ) * span + 0.5 );
+ else
+ val = (int)( ( axis._scale._min - scrollMin ) / ( scrollMin2 - scrollMin ) *
+ span + 0.5 );
+ */
+ if ( val < 0 )
+ val = 0;
+ else if ( val > span )
+ val = span;
+
+ //if ( ( axis is XAxis && axis.IsReverse ) || ( ( ! axis is XAxis ) && ! axis.IsReverse ) )
+ if ( ( axis is XAxis ) == axis.Scale.IsReverse )
+ val = span - val;
+
+ if ( val < scrollBar.Minimum )
+ val = scrollBar.Minimum;
+ if ( val > scrollBar.Maximum )
+ val = scrollBar.Maximum;
+
+ scrollBar.Value = val;
+ scrollBar.Enabled = true;
+ //scrollBar.Visible = true;
+ }
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ZedGraphControl.cs b/ZedGraph/ZedGraphControl.cs
new file mode 100644
index 0000000..b0b5b55
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.cs
@@ -0,0 +1,850 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Drawing.Imaging;
+using System.Drawing.Printing;
+using System.Data;
+using System.Globalization;
+using System.IO;
+using System.Resources;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+
+namespace ZedGraph
+{
+/*
+ /// <summary>
+ ///
+ /// </summary>
+ public struct DrawingThreadData
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ public Graphics _g;
+ /// <summary>
+ ///
+ /// </summary>
+ public MasterPane _masterPane;
+
+// public DrawingThread( Graphics g, MasterPane masterPane )
+// {
+// _g = g;
+// _masterPane = masterPane;
+// }
+ }
+*/
+
+ /// <summary>
+ /// The ZedGraphControl class provides a UserControl interface to the
+ /// <see cref="ZedGraph"/> class library. This allows ZedGraph to be installed
+ /// as a control in the Visual Studio toolbox. You can use the control by simply
+ /// dragging it onto a form in the Visual Studio form editor. All graph
+ /// attributes are accessible via the <see cref="ZedGraphControl.GraphPane"/>
+ /// property.
+ /// </summary>
+ /// <author> John Champion revised by Jerry Vos </author>
+ /// <version> $Revision: 3.86 $ $Date: 2007-11-03 04:41:29 $ </version>
+ public partial class ZedGraphControl : UserControl
+ {
+
+ #region Private Fields
+
+ /// <summary>
+ /// This private field contains the instance for the MasterPane object of this control.
+ /// You can access the MasterPane object through the public property
+ /// <see cref="ZedGraphControl.MasterPane"/>. This is nulled when this Control is
+ /// disposed.
+ /// </summary>
+ private MasterPane _masterPane;
+
+ /// <summary>
+ /// private field that determines whether or not tooltips will be displayed
+ /// when the mouse hovers over data values. Use the public property
+ /// <see cref="IsShowPointValues"/> to access this value.
+ /// </summary>
+ private bool _isShowPointValues = false;
+ /// <summary>
+ /// private field that determines whether or not tooltips will be displayed
+ /// showing the scale values while the mouse is located within the ChartRect.
+ /// Use the public property <see cref="IsShowCursorValues"/> to access this value.
+ /// </summary>
+ private bool _isShowCursorValues = false;
+ /// <summary>
+ /// private field that determines the format for displaying tooltip values.
+ /// This format is passed to <see cref="PointPairBase.ToString(string)"/>.
+ /// Use the public property <see cref="PointValueFormat"/> to access this
+ /// value.
+ /// </summary>
+ private string _pointValueFormat = PointPair.DefaultFormat;
+
+ /// <summary>
+ /// private field that determines whether or not the context menu will be available. Use the
+ /// public property <see cref="IsShowContextMenu"/> to access this value.
+ /// </summary>
+ private bool _isShowContextMenu = true;
+
+ /// <summary>
+ /// private field that determines whether or not a message box will be shown in response to
+ /// a context menu "Copy" command. Use the
+ /// public property <see cref="IsShowCopyMessage"/> to access this value.
+ /// </summary>
+ /// <remarks>
+ /// Note that, if this value is set to false, the user will receive no indicative feedback
+ /// in response to a Copy action.
+ /// </remarks>
+ private bool _isShowCopyMessage = true;
+
+ private SaveFileDialog _saveFileDialog = new SaveFileDialog();
+
+ /// <summary>
+ /// private field that determines whether the settings of
+ /// <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and <see cref="PaneBase.IsPenWidthScaled" />
+ /// will be overridden to true during printing operations.
+ /// </summary>
+ /// <remarks>
+ /// Printing involves pixel maps that are typically of a dramatically different dimension
+ /// than on-screen pixel maps. Therefore, it becomes more important to scale the fonts and
+ /// lines to give a printed image that looks like what is shown on-screen. The default
+ /// setting for <see cref="ZedGraph.PaneBase.IsFontsScaled" /> is true, but the default
+ /// setting for <see cref="PaneBase.IsPenWidthScaled" /> is false.
+ /// </remarks>
+ /// <value>
+ /// A value of true will cause both <see cref="ZedGraph.PaneBase.IsFontsScaled" /> and
+ /// <see cref="PaneBase.IsPenWidthScaled" /> to be temporarily set to true during
+ /// printing operations.
+ /// </value>
+ private bool _isPrintScaleAll = true;
+ /// <summary>
+ /// private field that determines whether or not the visible aspect ratio of the
+ /// <see cref="MasterPane" /> <see cref="PaneBase.Rect" /> will be preserved
+ /// when printing this <see cref="ZedGraphControl" />.
+ /// </summary>
+ private bool _isPrintKeepAspectRatio = true;
+ /// <summary>
+ /// private field that determines whether or not the <see cref="MasterPane" />
+ /// <see cref="PaneBase.Rect" /> dimensions will be expanded to fill the
+ /// available space when printing this <see cref="ZedGraphControl" />.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="IsPrintKeepAspectRatio" /> is also true, then the <see cref="MasterPane" />
+ /// <see cref="PaneBase.Rect" /> dimensions will be expanded to fit as large
+ /// a space as possible while still honoring the visible aspect ratio.
+ /// </remarks>
+ private bool _isPrintFillPage = true;
+
+ /// <summary>
+ /// private field that determines the format for displaying tooltip date values.
+ /// This format is passed to <see cref="XDate.ToString(string)"/>.
+ /// Use the public property <see cref="PointDateFormat"/> to access this
+ /// value.
+ /// </summary>
+ private string _pointDateFormat = XDate.DefaultFormatStr;
+
+ /// <summary>
+ /// private value that determines whether or not zooming is enabled for the control in the
+ /// vertical direction. Use the public property <see cref="IsEnableVZoom"/> to access this
+ /// value.
+ /// </summary>
+ private bool _isEnableVZoom = true;
+ /// <summary>
+ /// private value that determines whether or not zooming is enabled for the control in the
+ /// horizontal direction. Use the public property <see cref="IsEnableHZoom"/> to access this
+ /// value.
+ /// </summary>
+ private bool _isEnableHZoom = true;
+
+ /// <summary>
+ /// private value that determines whether or not zooming is enabled with the mousewheel.
+ /// Note that this property is used in combination with the <see cref="IsEnableHZoom"/> and
+ /// <see cref="IsEnableVZoom" /> properties to control zoom options.
+ /// </summary>
+ private bool _isEnableWheelZoom = true;
+
+ /// <summary>
+ /// private value that determines whether or not point editing is enabled in the
+ /// vertical direction. Use the public property <see cref="IsEnableVEdit"/> to access this
+ /// value.
+ /// </summary>
+ private bool _isEnableVEdit = false;
+ /// <summary>
+ /// private value that determines whether or not point editing is enabled in the
+ /// horizontal direction. Use the public property <see cref="IsEnableHEdit"/> to access this
+ /// value.
+ /// </summary>
+ private bool _isEnableHEdit = false;
+
+ /// <summary>
+ /// private value that determines whether or not panning is allowed for the control in the
+ /// horizontal direction. Use the
+ /// public property <see cref="IsEnableHPan"/> to access this value.
+ /// </summary>
+ private bool _isEnableHPan = true;
+ /// <summary>
+ /// private value that determines whether or not panning is allowed for the control in the
+ /// vertical direction. Use the
+ /// public property <see cref="IsEnableVPan"/> to access this value.
+ /// </summary>
+ private bool _isEnableVPan = true;
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Internal variable that indicates if the control can manage selections.
+ /// </summary>
+ private bool _isEnableSelection = false;
+
+ private double _zoomStepFraction = 0.1;
+
+ private ScrollRange _xScrollRange;
+
+ private ScrollRangeList _yScrollRangeList;
+ private ScrollRangeList _y2ScrollRangeList;
+
+ private bool _isShowHScrollBar = false;
+ private bool _isShowVScrollBar = false;
+ //private bool isScrollY2 = false;
+ private bool _isAutoScrollRange = false;
+
+ private double _scrollGrace = 0.00; //0.05;
+
+ private bool _isSynchronizeXAxes = false;
+ private bool _isSynchronizeYAxes = false;
+
+ //private System.Windows.Forms.HScrollBar hScrollBar1;
+ //private System.Windows.Forms.VScrollBar vScrollBar1;
+
+ // The range of values to use the scroll control bars
+ private const int _ScrollControlSpan = int.MaxValue;
+ // The ratio of the largeChange to the smallChange for the scroll bars
+ private const int _ScrollSmallRatio = 10;
+
+ private bool _isZoomOnMouseCenter = false;
+
+ private ResourceManager _resourceManager;
+
+ /// <summary>
+ /// private field that stores a <see cref="PrintDocument" /> instance, which maintains
+ /// a persistent selection of printer options.
+ /// </summary>
+ /// <remarks>
+ /// This is needed so that a "Print" action utilizes the settings from a prior
+ /// "Page Setup" action.</remarks>
+ private PrintDocument _pdSave = null;
+ //private PrinterSettings printSave = null;
+ //private PageSettings pageSave = null;
+
+ /// <summary>
+ /// This private field contains a list of selected CurveItems.
+ /// </summary>
+ //private List<CurveItem> _selection = new List<CurveItem>();
+ private Selection _selection = new Selection();
+
+ #endregion
+
+ #region Fields: Buttons & Keys Properties
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to click on
+ /// linkable objects
+ /// </summary>
+ /// <seealso cref="LinkModifierKeys" />
+ private MouseButtons _linkButtons = MouseButtons.Left;
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to click
+ /// on linkable objects
+ /// </summary>
+ /// <seealso cref="LinkButtons" />
+ private Keys _linkModifierKeys = Keys.Alt;
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to edit point
+ /// data values
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHEdit" /> and/or
+ /// <see cref="IsEnableVEdit" /> are true.
+ /// </remarks>
+ /// <seealso cref="EditModifierKeys" />
+ private MouseButtons _editButtons = MouseButtons.Right;
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to edit point
+ /// data values
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHEdit" /> and/or
+ /// <see cref="IsEnableVEdit" /> are true.
+ /// </remarks>
+ /// <seealso cref="EditButtons" />
+ private Keys _editModifierKeys = Keys.Alt;
+
+ /// <summary>
+ /// Gets or sets a value that determines which mouse button will be used to select
+ /// <see cref="CurveItem" />'s.
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableSelection" /> is true.
+ /// </remarks>
+ /// <seealso cref="SelectModifierKeys" />
+ private MouseButtons _selectButtons = MouseButtons.Left;
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to select
+ /// <see cref="CurveItem" />'s.
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableSelection" /> is true.
+ /// </remarks>
+ /// <seealso cref="SelectButtons" />
+ private Keys _selectModifierKeys = Keys.Shift;
+
+ private Keys _selectAppendModifierKeys = Keys.Shift | Keys.Control;
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to perform
+ /// zoom operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHZoom" /> and/or
+ /// <see cref="IsEnableVZoom" /> are true.
+ /// </remarks>
+ /// <seealso cref="ZoomModifierKeys" />
+ /// <seealso cref="ZoomButtons2" />
+ /// <seealso cref="ZoomModifierKeys2" />
+ private MouseButtons _zoomButtons = MouseButtons.Left;
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to perform
+ /// zoom operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHZoom" /> and/or
+ /// <see cref="IsEnableVZoom" /> are true.
+ /// </remarks>
+ /// <seealso cref="ZoomButtons" />
+ /// <seealso cref="ZoomButtons2" />
+ /// <seealso cref="ZoomModifierKeys2" />
+ private Keys _zoomModifierKeys = Keys.None;
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used as a
+ /// secondary option to perform zoom operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHZoom" /> and/or
+ /// <see cref="IsEnableVZoom" /> are true.
+ /// </remarks>
+ /// <seealso cref="ZoomModifierKeys2" />
+ /// <seealso cref="ZoomButtons" />
+ /// <seealso cref="ZoomModifierKeys" />
+ private MouseButtons _zoomButtons2 = MouseButtons.None;
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used as a
+ /// secondary option to perform zoom operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHZoom" /> and/or
+ /// <see cref="IsEnableVZoom" /> are true.
+ /// </remarks>
+ /// <seealso cref="ZoomButtons" />
+ /// <seealso cref="ZoomButtons2" />
+ /// <seealso cref="ZoomModifierKeys2" />
+ private Keys _zoomModifierKeys2 = Keys.None;
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used to perform
+ /// panning operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHPan" /> and/or
+ /// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
+ /// the mouse) should not be confused with a scroll operation (using a scroll bar to
+ /// move the graph).
+ /// </remarks>
+ /// <seealso cref="PanModifierKeys" />
+ /// <seealso cref="PanButtons2" />
+ /// <seealso cref="PanModifierKeys2" />
+ private MouseButtons _panButtons = MouseButtons.Left;
+
+ // Setting this field to Keys.Shift here
+ // causes an apparent bug to crop up in VS 2003, by which it will have the value:
+ // "System.Windows.Forms.Keys.Shift+None", which won't compile
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used to perform
+ /// panning operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHPan" /> and/or
+ /// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
+ /// the mouse) should not be confused with a scroll operation (using a scroll bar to
+ /// move the graph).
+ /// </remarks>
+ /// <seealso cref="PanButtons" />
+ /// <seealso cref="PanButtons2" />
+ /// <seealso cref="PanModifierKeys2" />
+ private Keys _panModifierKeys = Keys.Control;
+
+ /// <summary>
+ /// Gets or sets a value that determines which Mouse button will be used as a
+ /// secondary option to perform panning operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHPan" /> and/or
+ /// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
+ /// the mouse) should not be confused with a scroll operation (using a scroll bar to
+ /// move the graph).
+ /// </remarks>
+ /// <seealso cref="PanModifierKeys2" />
+ /// <seealso cref="PanButtons" />
+ /// <seealso cref="PanModifierKeys" />
+ private MouseButtons _panButtons2 = MouseButtons.Middle;
+
+ // Setting this field to Keys.Shift here
+ // causes an apparent bug to crop up in VS 2003, by which it will have the value:
+ // "System.Windows.Forms.Keys.Shift+None", which won't compile
+ /// <summary>
+ /// Gets or sets a value that determines which modifier keys will be used as a
+ /// secondary option to perform panning operations
+ /// </summary>
+ /// <remarks>
+ /// This setting only applies if <see cref="IsEnableHPan" /> and/or
+ /// <see cref="IsEnableVPan" /> are true. A Pan operation (dragging the graph with
+ /// the mouse) should not be confused with a scroll operation (using a scroll bar to
+ /// move the graph).
+ /// </remarks>
+ /// <seealso cref="PanButtons2" />
+ /// <seealso cref="PanButtons" />
+ /// <seealso cref="PanModifierKeys" />
+ private Keys _panModifierKeys2 = Keys.None;
+
+ #endregion
+
+ #region Fields: Temporary state variables
+
+ /// <summary>
+ /// Internal variable that indicates the control is currently being zoomed.
+ /// </summary>
+ private bool _isZooming = false;
+ /// <summary>
+ /// Internal variable that indicates the control is currently being panned.
+ /// </summary>
+ private bool _isPanning = false;
+ /// <summary>
+ /// Internal variable that indicates a point value is currently being edited.
+ /// </summary>
+ private bool _isEditing = false;
+
+ // Revision: JCarpenter 10/06
+ /// <summary>
+ /// Internal variable that indicates the control is currently using selection.
+ /// </summary>
+ private bool _isSelecting = false;
+
+ /// <summary>
+ /// Internal variable that stores the <see cref="GraphPane"/> reference for the Pane that is
+ /// currently being zoomed or panned.
+ /// </summary>
+ private GraphPane _dragPane = null;
+ /// <summary>
+ /// Internal variable that stores a rectangle which is either the zoom rectangle, or the incremental
+ /// pan amount since the last mousemove event.
+ /// </summary>
+ private Point _dragStartPt;
+ private Point _dragEndPt;
+
+ private int _dragIndex;
+ private CurveItem _dragCurve;
+ private PointPair _dragStartPair;
+ /// <summary>
+ /// private field that stores the state of the scale ranges prior to starting a panning action.
+ /// </summary>
+ private ZoomState _zoomState;
+ private ZoomStateStack _zoomStateStack;
+
+ //temporarily save the location of a context menu click so we can use it for reference
+ // Note that Control.MousePosition ends up returning the position after the mouse has
+ // moved to the menu item within the context menu. Therefore, this point is saved so
+ // that we have the point at which the context menu was first right-clicked
+ internal Point _menuClickPt;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public ZedGraphControl()
+ {
+ InitializeComponent();
+
+ // These commands do nothing, but they get rid of the compiler warnings for
+ // unused events
+ bool b = MouseDown == null || MouseUp == null || MouseMove == null;
+
+ // Link in these events from the base class, since we disable them from this class.
+ base.MouseDown += new System.Windows.Forms.MouseEventHandler( this.ZedGraphControl_MouseDown );
+ base.MouseUp += new System.Windows.Forms.MouseEventHandler( this.ZedGraphControl_MouseUp );
+ base.MouseMove += new System.Windows.Forms.MouseEventHandler( this.ZedGraphControl_MouseMove );
+
+ //this.MouseWheel += new System.Windows.Forms.MouseEventHandler( this.ZedGraphControl_MouseWheel );
+
+ // Use double-buffering for flicker-free updating:
+ SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint
+ | ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true );
+ //isTransparentBackground = false;
+ //SetStyle( ControlStyles.Opaque, false );
+ SetStyle( ControlStyles.SupportsTransparentBackColor, true );
+ //this.BackColor = Color.Transparent;
+
+ _resourceManager = new ResourceManager( "ZedGraph.ZedGraph.ZedGraphLocale",
+ Assembly.GetExecutingAssembly() );
+
+ Rectangle rect = new Rectangle( 0, 0, this.Size.Width, this.Size.Height );
+ _masterPane = new MasterPane( "", rect );
+ _masterPane.Margin.All = 0;
+ _masterPane.Title.IsVisible = false;
+
+ string titleStr = _resourceManager.GetString( "title_def" );
+ string xStr = _resourceManager.GetString( "x_title_def" );
+ string yStr = _resourceManager.GetString( "y_title_def" );
+
+ //GraphPane graphPane = new GraphPane( rect, "Title", "X Axis", "Y Axis" );
+ GraphPane graphPane = new GraphPane( rect, titleStr, xStr, yStr );
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ graphPane.AxisChange( g );
+ //g.Dispose();
+ }
+ _masterPane.Add( graphPane );
+
+ this.hScrollBar1.Minimum = 0;
+ this.hScrollBar1.Maximum = 100;
+ this.hScrollBar1.Value = 0;
+
+ this.vScrollBar1.Minimum = 0;
+ this.vScrollBar1.Maximum = 100;
+ this.vScrollBar1.Value = 0;
+
+ _xScrollRange = new ScrollRange( true );
+ _yScrollRangeList = new ScrollRangeList();
+ _y2ScrollRangeList = new ScrollRangeList();
+
+ _yScrollRangeList.Add( new ScrollRange( true ) );
+ _y2ScrollRangeList.Add( new ScrollRange( false ) );
+
+ _zoomState = null;
+ _zoomStateStack = new ZoomStateStack();
+ }
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if the components should be
+ /// disposed, false otherwise</param>
+ protected override void Dispose( bool disposing )
+ {
+ lock ( this )
+ {
+ if ( disposing )
+ {
+ if ( components != null )
+ components.Dispose();
+ }
+ base.Dispose( disposing );
+
+ _masterPane = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Called by the system to update the control on-screen
+ /// </summary>
+ /// <param name="e">
+ /// A PaintEventArgs object containing the Graphics specifications
+ /// for this Paint event.
+ /// </param>
+ protected override void OnPaint( PaintEventArgs e )
+ {
+ lock ( this )
+ {
+ if ( BeenDisposed || _masterPane == null || this.GraphPane == null )
+ return;
+
+ if ( hScrollBar1 != null && this.GraphPane != null &&
+ vScrollBar1 != null && _yScrollRangeList != null )
+ {
+ SetScroll( hScrollBar1, this.GraphPane.XAxis, _xScrollRange.Min, _xScrollRange.Max );
+ SetScroll( vScrollBar1, this.GraphPane.YAxis, _yScrollRangeList[0].Min,
+ _yScrollRangeList[0].Max );
+ }
+
+ base.OnPaint( e );
+
+ // Add a try/catch pair since the users of the control can't catch this one
+ try { _masterPane.Draw( e.Graphics ); }
+ catch { }
+ }
+
+/*
+ // first, see if an old thread is still running
+ if ( t != null && t.IsAlive )
+ {
+ t.Abort();
+ }
+
+ //dt = new DrawingThread( e.Graphics, _masterPane );
+ //g = e.Graphics;
+
+ // Fire off the new thread
+ t = new Thread( new ParameterizedThreadStart( DoDrawingThread ) );
+ //ct.ApartmentState = ApartmentState.STA;
+ //ct.SetApartmentState( ApartmentState.STA );
+ DrawingThreadData dtd;
+ dtd._g = e.Graphics;
+ dtd._masterPane = _masterPane;
+
+ t.Start( dtd );
+ //ct.Join();
+*/
+ }
+
+// Thread t = null;
+ //DrawingThread dt = null;
+
+/*
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="dtdobj"></param>
+ public void DoDrawingThread( object dtdobj )
+ {
+ try
+ {
+ DrawingThreadData dtd = (DrawingThreadData) dtdobj;
+
+ if ( dtd._g != null && dtd._masterPane != null )
+ dtd._masterPane.Draw( dtd._g );
+
+ // else
+ // {
+ // using ( Graphics g2 = CreateGraphics() )
+ // _masterPane.Draw( g2 );
+ // }
+ }
+ catch
+ {
+
+ }
+ }
+*/
+
+ /// <summary>
+ /// Called when the control has been resized.
+ /// </summary>
+ /// <param name="sender">
+ /// A reference to the control that has been resized.
+ /// </param>
+ /// <param name="e">
+ /// An EventArgs object.
+ /// </param>
+ protected void ZedGraphControl_ReSize( object sender, System.EventArgs e )
+ {
+ lock ( this )
+ {
+ if ( BeenDisposed || _masterPane == null )
+ return;
+
+ Size newSize = this.Size;
+
+ if ( _isShowHScrollBar )
+ {
+ hScrollBar1.Visible = true;
+ newSize.Height -= this.hScrollBar1.Size.Height;
+ hScrollBar1.Location = new Point( 0, newSize.Height );
+ hScrollBar1.Size = new Size( newSize.Width, hScrollBar1.Height );
+ }
+ else
+ hScrollBar1.Visible = false;
+
+ if ( _isShowVScrollBar )
+ {
+ vScrollBar1.Visible = true;
+ newSize.Width -= this.vScrollBar1.Size.Width;
+ vScrollBar1.Location = new Point( newSize.Width, 0 );
+ vScrollBar1.Size = new Size( vScrollBar1.Width, newSize.Height );
+ }
+ else
+ vScrollBar1.Visible = false;
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ _masterPane.ReSize( g, new RectangleF( 0, 0, newSize.Width, newSize.Height ) );
+ //g.Dispose();
+ }
+ this.Invalidate();
+ }
+ }
+ /// <summary>This performs an axis change command on the graphPane.
+ /// </summary>
+ /// <remarks>
+ /// This is the same as
+ /// <c>ZedGraphControl.GraphPane.AxisChange( ZedGraphControl.CreateGraphics() )</c>, however,
+ /// this method also calls <see cref="SetScrollRangeFromData" /> if <see cref="IsAutoScrollRange" />
+ /// is true.
+ /// </remarks>
+ public virtual void AxisChange()
+ {
+ lock ( this )
+ {
+ if ( BeenDisposed || _masterPane == null )
+ return;
+
+ using ( Graphics g = this.CreateGraphics() )
+ {
+ _masterPane.AxisChange( g );
+ //g.Dispose();
+ }
+
+ if ( _isAutoScrollRange )
+ SetScrollRangeFromData();
+ }
+ }
+ #endregion
+
+ #region Zoom States
+
+ /// <summary>
+ /// Save the current states of the GraphPanes to a separate collection. Save a single
+ /// (<see paramref="primaryPane" />) GraphPane if the panes are not synchronized
+ /// (see <see cref="IsSynchronizeXAxes" /> and <see cref="IsSynchronizeYAxes" />),
+ /// or save a list of states for all GraphPanes if the panes are synchronized.
+ /// </summary>
+ /// <param name="primaryPane">The primary GraphPane on which zoom/pan/scroll operations
+ /// are taking place</param>
+ /// <param name="type">The <see cref="ZoomState.StateType" /> that describes the
+ /// current operation</param>
+ /// <returns>The <see cref="ZoomState" /> that corresponds to the
+ /// <see paramref="primaryPane" />.
+ /// </returns>
+ private ZoomState ZoomStateSave( GraphPane primaryPane, ZoomState.StateType type )
+ {
+ ZoomStateClear();
+
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ {
+ ZoomState state = new ZoomState( pane, type );
+ if ( pane == primaryPane )
+ _zoomState = state;
+ _zoomStateStack.Add( state );
+ }
+ }
+ else
+ _zoomState = new ZoomState( primaryPane, type );
+
+ return _zoomState;
+ }
+
+ /// <summary>
+ /// Restore the states of the GraphPanes to a previously saved condition (via
+ /// <see cref="ZoomStateSave" />. This is essentially an "undo" for live
+ /// pan and scroll actions. Restores a single
+ /// (<see paramref="primaryPane" />) GraphPane if the panes are not synchronized
+ /// (see <see cref="IsSynchronizeXAxes" /> and <see cref="IsSynchronizeYAxes" />),
+ /// or save a list of states for all GraphPanes if the panes are synchronized.
+ /// </summary>
+ /// <param name="primaryPane">The primary GraphPane on which zoom/pan/scroll operations
+ /// are taking place</param>
+ private void ZoomStateRestore( GraphPane primaryPane )
+ {
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ for ( int i = 0; i < _masterPane._paneList.Count; i++ )
+ {
+ if ( i < _zoomStateStack.Count )
+ _zoomStateStack[i].ApplyState( _masterPane._paneList[i] );
+ }
+ }
+ else if ( _zoomState != null )
+ _zoomState.ApplyState( primaryPane );
+
+ ZoomStateClear();
+ }
+
+ /// <summary>
+ /// Place the previously saved states of the GraphPanes on the individual GraphPane
+ /// <see cref="ZedGraph.GraphPane.ZoomStack" /> collections. This provides for an
+ /// option to undo the state change at a later time. Save a single
+ /// (<see paramref="primaryPane" />) GraphPane if the panes are not synchronized
+ /// (see <see cref="IsSynchronizeXAxes" /> and <see cref="IsSynchronizeYAxes" />),
+ /// or save a list of states for all GraphPanes if the panes are synchronized.
+ /// </summary>
+ /// <param name="primaryPane">The primary GraphPane on which zoom/pan/scroll operations
+ /// are taking place</param>
+ /// <returns>The <see cref="ZoomState" /> that corresponds to the
+ /// <see paramref="primaryPane" />.
+ /// </returns>
+ private void ZoomStatePush( GraphPane primaryPane )
+ {
+ if ( _isSynchronizeXAxes || _isSynchronizeYAxes )
+ {
+ for ( int i = 0; i < _masterPane._paneList.Count; i++ )
+ {
+ if ( i < _zoomStateStack.Count )
+ _masterPane._paneList[i].ZoomStack.Add( _zoomStateStack[i] );
+ }
+ }
+ else if ( _zoomState != null )
+ primaryPane.ZoomStack.Add( _zoomState );
+
+ ZoomStateClear();
+ }
+
+ /// <summary>
+ /// Clear the collection of saved states.
+ /// </summary>
+ private void ZoomStateClear()
+ {
+ _zoomStateStack.Clear();
+ _zoomState = null;
+ }
+
+ /// <summary>
+ /// Clear all states from the undo stack for each GraphPane.
+ /// </summary>
+ private void ZoomStatePurge()
+ {
+ foreach ( GraphPane pane in _masterPane._paneList )
+ pane.ZoomStack.Clear();
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ZedGraph/ZedGraphControl.resx b/ZedGraph/ZedGraphControl.resx
new file mode 100644
index 0000000..19dc0dd
--- /dev/null
+++ b/ZedGraph/ZedGraphControl.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
\ No newline at end of file
diff --git a/ZedGraph/ZedGraphException.cs b/ZedGraph/ZedGraphException.cs
new file mode 100644
index 0000000..65bf359
--- /dev/null
+++ b/ZedGraph/ZedGraphException.cs
@@ -0,0 +1,77 @@
+//============================================================================
+//ZedGraphException Class
+//Copyright � 2004 Jerry Vos
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+using System;
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// An exception thrown by ZedGraph. A child class of <see cref="ApplicationException"/>.
+ /// </summary>
+ ///
+ /// <author> Jerry Vos modified by John Champion</author>
+ /// <version> $Revision: 3.2 $ $Date: 2006-06-24 20:26:44 $ </version>
+ public class ZedGraphException : System.ApplicationException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ZedGraphException"/>
+ /// class with serialized data.
+ /// </summary>
+ /// <param name="info">The <see cref="System.Runtime.Serialization.SerializationInfo"/>
+ /// instance that holds the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="System.Runtime.Serialization.StreamingContext"/>
+ /// instance that contains contextual information about the source or destination.</param>
+ protected ZedGraphException( System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context )
+ : base ( info, context )
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Exception"/> class with a specified
+ /// error message and a reference to the inner exception that is the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.
+ /// If the innerException parameter is not a null reference, the current exception is raised
+ /// in a catch block that handles the inner exception.</param>
+ public ZedGraphException( System.String message, System.Exception innerException )
+ : base ( message, innerException )
+ {
+
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Exception"/> class with a specified error message.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ public ZedGraphException ( System.String message )
+ : base( message )
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Exception"/> class.
+ /// </summary>
+ public ZedGraphException()
+ : base()
+ {
+ }
+ }
+}
diff --git a/ZedGraph/ZedGraphLocale.resx b/ZedGraph/ZedGraphLocale.resx
new file mode 100644
index 0000000..962f7e9
--- /dev/null
+++ b/ZedGraph/ZedGraphLocale.resx
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="copy" xml:space="preserve">
+ <value>Copy</value>
+ </data>
+ <data name="copied_to_clip" xml:space="preserve">
+ <value>Image copied to clipboard</value>
+ </data>
+ <data name="save_as" xml:space="preserve">
+ <value>Save Image As...</value>
+ </data>
+ <data name="set_default" xml:space="preserve">
+ <value>Set Scale to Default</value>
+ </data>
+ <data name="show_val" xml:space="preserve">
+ <value>Show Point Values</value>
+ </data>
+ <data name="title_def" xml:space="preserve">
+ <value>Title</value>
+ </data>
+ <data name="undo_all" xml:space="preserve">
+ <value>Undo All Zoom/Pan</value>
+ </data>
+ <data name="unpan" xml:space="preserve">
+ <value>Un-Pan</value>
+ </data>
+ <data name="unzoom" xml:space="preserve">
+ <value>Un-Zoom</value>
+ </data>
+ <data name="x_title_def" xml:space="preserve">
+ <value>X Axis</value>
+ </data>
+ <data name="y_title_def" xml:space="preserve">
+ <value>Y Axis</value>
+ </data>
+ <data name="unscroll" xml:space="preserve">
+ <value>Undo Scroll</value>
+ </data>
+ <data name="page_setup" xml:space="preserve">
+ <value>Page Setup...</value>
+ </data>
+ <data name="print" xml:space="preserve">
+ <value>Print...</value>
+ </data>
+</root>
\ No newline at end of file
diff --git a/ZedGraph/ZoomState.cs b/ZedGraph/ZoomState.cs
new file mode 100644
index 0000000..7a6c5e1
--- /dev/null
+++ b/ZedGraph/ZoomState.cs
@@ -0,0 +1,191 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright © 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Text;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A class that captures all the scale range settings for a <see cref="GraphPane"/>.
+ /// </summary>
+ /// <remarks>
+ /// This class is used to store scale ranges in order to allow zooming out to
+ /// prior scale range states. <see cref="ZoomState"/> objects are maintained in the
+ /// <see cref="ZoomStateStack"/> collection. The <see cref="ZoomState"/> object holds
+ /// a <see cref="ScaleState"/> object for each of the three axes; the <see cref="XAxis"/>,
+ /// the <see cref="YAxis"/>, and the <see cref="Y2Axis"/>.
+ /// </remarks>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.15 $ $Date: 2007-04-16 00:03:07 $ </version>
+ public class ZoomState : ICloneable
+ {
+ /// <summary>
+ /// An enumeration that describes whether a given state is the result of a Pan or Zoom
+ /// operation.
+ /// </summary>
+ public enum StateType
+ {
+ /// <summary>
+ /// Indicates the <see cref="ZoomState"/> object is from a Zoom operation
+ /// </summary>
+ Zoom,
+ /// <summary>
+ /// Indicates the <see cref="ZoomState"/> object is from a Wheel Zoom operation
+ /// </summary>
+ WheelZoom,
+ /// <summary>
+ /// Indicates the <see cref="ZoomState"/> object is from a Pan operation
+ /// </summary>
+ Pan,
+ /// <summary>
+ /// Indicates the <see cref="ZoomState"/> object is from a Scroll operation
+ /// </summary>
+ Scroll
+ }
+
+ /// <summary>
+ /// <see cref="ScaleState"/> objects to store the state data from the axes.
+ /// </summary>
+ private ScaleState _xAxis, _x2Axis;
+ private ScaleStateList _yAxis, _y2Axis;
+ /// <summary>
+ /// An enum value indicating the type of adjustment being made to the
+ /// scale range state.
+ /// </summary>
+ private StateType _type;
+
+ /// <summary>
+ /// Gets a <see cref="StateType" /> value indicating the type of action (zoom or pan)
+ /// saved by this <see cref="ZoomState" />.
+ /// </summary>
+ public StateType Type
+ {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Gets a string representing the type of adjustment that was made when this scale
+ /// state was saved.
+ /// </summary>
+ /// <value>A string representation for the state change type; typically
+ /// "Pan", "Zoom", or "Scroll".</value>
+ public string TypeString
+ {
+ get
+ {
+ switch ( _type )
+ {
+ case StateType.Pan:
+ return "Pan";
+ case StateType.WheelZoom:
+ return "WheelZoom";
+ case StateType.Zoom:
+ default:
+ return "Zoom";
+ case StateType.Scroll:
+ return "Scroll";
+ }
+ }
+ }
+
+ /// <summary>
+ /// Construct a <see cref="ZoomState"/> object from the scale ranges settings contained
+ /// in the specified <see cref="GraphPane"/>.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> from which to obtain the scale
+ /// range values.
+ /// </param>
+ /// <param name="type">A <see cref="StateType"/> enumeration that indicates whether
+ /// this saved state is from a pan or zoom.</param>
+ public ZoomState( GraphPane pane, StateType type )
+ {
+
+ _xAxis = new ScaleState( pane.XAxis );
+ _x2Axis = new ScaleState( pane.X2Axis );
+ _yAxis = new ScaleStateList( pane.YAxisList );
+ _y2Axis = new ScaleStateList( pane.Y2AxisList );
+ _type = type;
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ZoomState"/> object from which to copy</param>
+ public ZoomState( ZoomState rhs )
+ {
+ _xAxis = new ScaleState( rhs._xAxis );
+ _x2Axis = new ScaleState( rhs._x2Axis );
+ _yAxis = new ScaleStateList( rhs._yAxis );
+ _y2Axis = new ScaleStateList( rhs._y2Axis );
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ZoomState Clone()
+ {
+ return new ZoomState( this );
+ }
+
+
+ /// <summary>
+ /// Copy the properties from this <see cref="ZoomState"/> out to the specified <see cref="GraphPane"/>.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> to which the scale range properties should be
+ /// copied.</param>
+ public void ApplyState( GraphPane pane )
+ {
+ _xAxis.ApplyScale( pane.XAxis );
+ _x2Axis.ApplyScale( pane.X2Axis );
+ _yAxis.ApplyScale( pane.YAxisList );
+ _y2Axis.ApplyScale( pane.Y2AxisList );
+ }
+
+ /// <summary>
+ /// Determine if the state contained in this <see cref="ZoomState"/> object is different from
+ /// the state of the specified <see cref="GraphPane"/>.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> object with which to compare states.</param>
+ /// <returns>true if the states are different, false otherwise</returns>
+ public bool IsChanged( GraphPane pane )
+ {
+ return _xAxis.IsChanged( pane.XAxis ) ||
+ _x2Axis.IsChanged( pane.X2Axis ) ||
+ _yAxis.IsChanged( pane.YAxisList ) ||
+ _y2Axis.IsChanged( pane.Y2AxisList );
+ }
+
+ }
+}
diff --git a/ZedGraph/ZoomStateStack.cs b/ZedGraph/ZoomStateStack.cs
new file mode 100644
index 0000000..374b404
--- /dev/null
+++ b/ZedGraph/ZoomStateStack.cs
@@ -0,0 +1,178 @@
+//============================================================================
+//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
+//Copyright � 2004 John Champion
+//
+//This library is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 of the License, or (at your option) any later version.
+//
+//This library is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser General Public
+//License along with this library; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//=============================================================================
+
+#region Using directives
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#endregion
+
+namespace ZedGraph
+{
+ /// <summary>
+ /// A LIFO stack of prior <see cref="ZoomState"/> objects, used to allow zooming out to prior
+ /// states (of scale range settings).
+ /// </summary>
+ /// <author> John Champion </author>
+ /// <version> $Revision: 3.1 $ $Date: 2006-06-24 20:26:44 $ </version>
+ public class ZoomStateStack : List<ZoomState>, ICloneable
+ {
+ /// <summary>
+ /// Default Constructor
+ /// </summary>
+ public ZoomStateStack()
+ {
+ }
+
+ /// <summary>
+ /// The Copy Constructor
+ /// </summary>
+ /// <param name="rhs">The <see cref="ZoomStateStack"/> object from which to copy</param>
+ public ZoomStateStack( ZoomStateStack rhs )
+ {
+ foreach ( ZoomState state in rhs )
+ {
+ Add( new ZoomState( state ) );
+ }
+ }
+
+ /// <summary>
+ /// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
+ /// calling the typed version of <see cref="Clone" />
+ /// </summary>
+ /// <returns>A deep copy of this object</returns>
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Typesafe, deep-copy clone method.
+ /// </summary>
+ /// <returns>A new, independent copy of this class</returns>
+ public ZoomStateStack Clone()
+ {
+ return new ZoomStateStack( this );
+ }
+
+
+ /// <summary>
+ /// Public readonly property that indicates if the stack is empty
+ /// </summary>
+ /// <value>true for an empty stack, false otherwise</value>
+ public bool IsEmpty
+ {
+ get { return this.Count == 0; }
+ }
+
+ /// <summary>
+ /// Add the scale range information from the specified <see cref="GraphPane"/> object as a
+ /// new <see cref="ZoomState"/> entry on the stack.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> object from which the scale range
+ /// information should be copied.</param>
+ /// <param name="type">A <see cref="ZoomState.StateType"/> enumeration that indicates whether this
+ /// state is the result of a zoom or pan operation.</param>
+ /// <returns>The resultant <see cref="ZoomState"/> object that was pushed on the stack.</returns>
+ public ZoomState Push( GraphPane pane, ZoomState.StateType type )
+ {
+ ZoomState state = new ZoomState( pane, type );
+ this.Add( state );
+ return state;
+ }
+
+ /// <summary>
+ /// Add the scale range information from the specified <see cref="ZoomState"/> object as a
+ /// new <see cref="ZoomState"/> entry on the stack.
+ /// </summary>
+ /// <param name="state">The <see cref="ZoomState"/> object to be placed on the stack.</param>
+ /// <returns>The <see cref="ZoomState"/> object (same as the <see paramref="state"/>
+ /// parameter).</returns>
+ public ZoomState Push( ZoomState state )
+ {
+ this.Add( state );
+ return state;
+ }
+
+ /// <summary>
+ /// Pop a <see cref="ZoomState"/> entry from the top of the stack, and apply the properties
+ /// to the specified <see cref="GraphPane"/> object.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> object to which the scale range
+ /// information should be copied.</param>
+ /// <returns>The <see cref="ZoomState"/> object that was "popped" from the stack and applied
+ /// to the specified <see cref="GraphPane"/>. null if no <see cref="ZoomState"/> was
+ /// available (the stack was empty).</returns>
+ public ZoomState Pop( GraphPane pane )
+ {
+ if ( !this.IsEmpty )
+ {
+ ZoomState state = (ZoomState) this[ this.Count - 1 ];
+ this.RemoveAt( this.Count - 1 );
+
+ state.ApplyState( pane );
+ return state;
+ }
+ else
+ return null;
+ }
+
+ /// <summary>
+ /// Pop the <see cref="ZoomState"/> entry from the bottom of the stack, and apply the properties
+ /// to the specified <see cref="GraphPane"/> object. Clear the stack completely.
+ /// </summary>
+ /// <param name="pane">The <see cref="GraphPane"/> object to which the scale range
+ /// information should be copied.</param>
+ /// <returns>The <see cref="ZoomState"/> object at the bottom of the stack that was applied
+ /// to the specified <see cref="GraphPane"/>. null if no <see cref="ZoomState"/> was
+ /// available (the stack was empty).</returns>
+ public ZoomState PopAll( GraphPane pane )
+ {
+ if ( !this.IsEmpty )
+ {
+ ZoomState state = (ZoomState) this[ 0 ];
+ this.Clear();
+
+ state.ApplyState( pane );
+
+ return state;
+ }
+ else
+ return null;
+ }
+
+ /// <summary>
+ /// Gets a reference to the <see cref="ZoomState"/> object at the top of the stack,
+ /// without actually removing it from the stack.
+ /// </summary>
+ /// <value>A <see cref="ZoomState"/> object reference, or null if the stack is empty.</value>
+ public ZoomState Top
+ {
+ get
+ {
+ if ( !this.IsEmpty )
+ return (ZoomState) this[ this.Count - 1 ];
+ else
+ return null;
+ }
+ }
+ }
+}
diff --git a/zedgraphkey.snk b/zedgraphkey.snk
new file mode 100644
index 0000000..51fbca4
Binary files /dev/null and b/zedgraphkey.snk differ