Пример #1
0
 /// <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());
     }
 }
        private float GetMaxHeight(PaneList paneList, Graphics g, float scaleFactor)
        {
            scaleFactor = Math.Min(scaleFactor, 1F * (g.DpiX / 72.0f));

            // Set up some scaled dimensions for calculating sizes and locations
            float charHeight = this.FontSpec.GetHeight(scaleFactor);

            // 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 &&
                        curve._label._fontSpec != null)
                    {
                        float tmpHeight = curve._label._fontSpec.GetHeight(scaleFactor);
                        if (tmpHeight > charHeight)
                        {
                            charHeight = tmpHeight;
                        }
                    }
                }
            }

            return(charHeight);
        }
Пример #3
0
 /// <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() );
     }
 }
Пример #4
0
        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);
        }
Пример #5
0
        /// <summary>
        /// The Copy Constructor
        /// </summary>
        /// <param name="rhs">The <see cref="MasterPane"/> object from which to copy</param>
        public MasterPane(MasterPane rhs) : base(rhs)
        {
            this.paneLayout              = rhs.paneLayout;
            this.innerPaneGap            = rhs.innerPaneGap;
            this.rows                    = rhs.rows;
            this.columns                 = rhs.rows;
            this.isColumnSpecified       = rhs.isColumnSpecified;
            this.countList               = rhs.countList;
            this.hasUniformLegendEntries = rhs.hasUniformLegendEntries;

            this.paneList = (PaneList)rhs.paneList.Clone();
        }
Пример #6
0
        /// <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.PaneRect"/>.
        /// </summary>
        public MasterPane(string title, RectangleF paneRect) : base(title, paneRect)
        {
            this.paneLayout              = Default.PaneLayout;
            this.innerPaneGap            = Default.InnerPaneGap;
            this.rows                    = -1;
            this.columns                 = -1;
            this.isColumnSpecified       = false;
            this.countList               = null;
            this.hasUniformLegendEntries = Default.hasUniformLegendEntries;

            this.paneList = new PaneList();

            this.legend.IsVisible = Default.IsShowLegend;
        }
Пример #7
0
        /// <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;

            InitLayout();
        }
Пример #8
0
        /// <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");

            this.paneList     = (PaneList)info.GetValue("paneList", typeof(PaneList));
            this.paneLayout   = (PaneLayout)info.GetValue("paneLayout", typeof(PaneLayout));
            this.innerPaneGap = info.GetSingle("innerPaneGap");

            this.rows                    = info.GetInt32("rows");
            this.columns                 = info.GetInt32("columns");
            this.isColumnSpecified       = info.GetBoolean("isColumnSpecified");
            this.countList               = (int[])info.GetValue("countList", typeof(int[]));
            this.hasUniformLegendEntries = info.GetBoolean("hasUniformLegendEntries");
        }
Пример #9
0
        /// <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;
        }
        /// <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)
        {
            scaleFactor = Math.Min(scaleFactor, 1F * (pane.m_Dpi / 72.0f));

            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);
            }
        }
Пример #11
0
        /// <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 (this.rect.Contains(mousePt))
            {
                float charHeight     = this.FontSpec.GetHeight(scaleFactor),
                      halfCharHeight = charHeight / 2.0F;
                int j = (int)((mousePt.Y - this.rect.Top) / charHeight);
                int i = (int)((mousePt.X - this.rect.Left - halfCharHeight) / this.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.IsLegendLabelVisible && curve.Label != "")
                        {
                            if (pos == 0)
                            {
                                return(true);
                            }
                            pos--;
                        }
                        index++;
                    }
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #12
0
        /// <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))
            {
                return(false);
            }

            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 (var tmpPane in paneList.Where(p => p is GraphPane).Cast <GraphPane>())
            {
                foreach (CurveItem curve in tmpPane.CurveList)
                {
                    if (curve.Label.IsVisible && curve.Label.Text != string.Empty)
                    {
                        if (pos == 0)
                        {
                            return(true);
                        }
                        pos--;
                    }
                    index++;
                }
            }

            return(true);
        }
Пример #13
0
        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);
        }
Пример #14
0
        /// <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[]));
        }
Пример #15
0
        private float GetMaxHeight(PaneList paneList, Graphics g, float scaleFactor)
        {
            // Set up some scaled dimensions for calculating sizes and locations
            float charHeight = this.FontSpec.GetHeight(scaleFactor);

            // 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 != "" && curve.IsLegendLabelVisible && curve.FontSpec != null)
                    {
                        float tmpHeight = curve.FontSpec.GetHeight(scaleFactor);
                        if (tmpHeight > charHeight)
                        {
                            charHeight = tmpHeight;
                        }
                    }
                }
            }

            return(charHeight);
        }
Пример #16
0
        /// <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 (_numberOfColumns <= 0)
            {
                _numberOfColumns = 1;
            }
            if (_legendItemWidth <= 0)
            {
                _legendItemWidth = 100;
            }
            if (_legendItemHeight <= 0)
            {
                _legendItemHeight = _tmpSize;
            }

            //float gap = pane.ScaledGap( scaleFactor );

            int iEntry = 0;

            // 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];

                        float x    = _rect.Left + halfGap / 2.0F + (iEntry % _numberOfColumns) * (_legendItemWidth);
                        float y    = _rect.Top + (int)(iEntry / _numberOfColumns) * _legendItemHeight;
                        float xEnd = DrawLabel(curve.Label, curve, g, pane, scaleFactor, tmpPane, _isShowLegendSymbols, x, y);
                        x = xEnd;
                        DrawLabel(curve.SecondaryLabel, curve, g, pane, scaleFactor, tmpPane, false, x, y);
                        iEntry += 1;
                    }
                    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);
                }
            }
        }
Пример #17
0
        /// <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);
                }
            }
        }
Пример #18
0
        /// <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 (!this.isVisible)
            {
                return;
            }

            // Fill the background with the specified color if required
            this.fill.Draw(g, this.rect);

            // Set up some scaled dimensions for calculating sizes and locations
            float charHeight     = this.FontSpec.GetHeight(scaleFactor),
                  halfCharHeight = charHeight / 2.0F;
            float charWidth      = this.FontSpec.GetWidth(g, scaleFactor);

            // Check for bad data values
            if (this.hStack <= 0)
            {
                this.hStack = 1;
            }
            if (this.legendItemWidth <= 0)
            {
                this.legendItemWidth = 100;
            }
            if (this.legendItemHeight <= 0)
            {
                this.legendItemHeight = charHeight;
            }

            //float gap = pane.ScaledGap( scaleFactor );

            int   iEntry = 0;
            float x, y;

            // Get a brush for the legend label text
            SolidBrush brushB = new SolidBrush(Color.Black);


            PaneList paneList = GetPaneList(pane);

            foreach (GraphPane tmpPane in paneList)
            {
                // Loop for each curve in the CurveList collection
                foreach (CurveItem curve in tmpPane.CurveList)
                {
                    if (curve.Label != "")
                    {
                        // 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 = this.rect.Left + halfCharHeight / 2.0F +
                            (iEntry % hStack) * this.legendItemWidth;
                        y = this.rect.Top + (int)(iEntry / hStack) * this.legendItemHeight;

                        // Draw the legend label for the current curve
                        this.FontSpec.Draw(g, pane.IsPenWidthScaled, curve.Label,
                                           x + 2.5F * charHeight, y + this.legendItemHeight / 2.0F,
                                           AlignH.Left, AlignV.Center, scaleFactor);

                        RectangleF rect = new RectangleF(x, y + this.legendItemHeight / 4.0F,
                                                         2 * charHeight, this.legendItemHeight / 2.0F);
                        curve.DrawLegendKey(g, tmpPane, rect, scaleFactor);

                        // maintain a curve count for positioning
                        iEntry++;
                    }
                }
                if (pane is MasterPane && ((MasterPane)pane).HasUniformLegendEntries)
                {
                    break;
                }
            }

            // Draw a border around the legend if required
            if (iEntry > 0)
            {
                this.Border.Draw(g, pane.IsPenWidthScaled, scaleFactor, this.rect);
            }
        }
Пример #19
0
        /// <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;
            _numberOfColumns  = 1;
            _legendItemWidth  = 1;
            _legendItemHeight = 0;

            RectangleF clientRect = pane.CalcClientRect(g, scaleFactor);

            // If the legend is invisible, don't do anything
            if (!_isVisible)
            {
                return;
            }

            int numberOfCurvesToDraw = 0;

            PaneList paneList = GetPaneList(pane);

            _tmpSize = GetMaxHeight(paneList, g, scaleFactor);

            float halfGap  = _tmpSize / 2.0F,
                  maxWidth = 0,
                  tmpWidth = 0,
                  gapPix   = _gap * _tmpSize;

            bool showingSecondaryLabel = false;

            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];
                    bool      atLeastOneLabelDrawn = false;
                    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;
                        }

                        atLeastOneLabelDrawn = true;
                    }
                    if (curve.SecondaryLabel._text != string.Empty && curve.SecondaryLabel._isVisible)
                    {
                        // Calculate the width of the label save the max width
                        FontSpec tmpFont = (curve.SecondaryLabel._fontSpec != null) ?
                                           curve.SecondaryLabel._fontSpec : this.FontSpec;

                        tmpWidth = tmpFont.GetWidth(g, curve.SecondaryLabel._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;
                        }

                        atLeastOneLabelDrawn  = true;
                        showingSecondaryLabel = true;
                    }

                    if (atLeastOneLabelDrawn)
                    {
                        ++numberOfCurvesToDraw;
                    }
                }

                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)
                {
                    if (showingSecondaryLabel)
                    {
                        _legendItemWidth = 3.0f * _tmpSize + maxWidth * 1.6f;
                    }
                    else
                    {
                        _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)
                {
                    _numberOfColumns = (int)((widthAvail - halfGap) / _legendItemWidth);
                }

                // You can never have more columns than legend entries
                if (_numberOfColumns > numberOfCurvesToDraw)
                {
                    _numberOfColumns = numberOfCurvesToDraw;
                }

                // a saftey check
                if (_numberOfColumns == 0)
                {
                    _numberOfColumns = 1;
                }
            }
            else
            {
                if (_isShowLegendSymbols)
                {
                    _legendItemWidth = 4.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 = _numberOfColumns * _legendItemWidth;

            // The total legend height
            _legendItemHeight = _legendItemHeight * (float)scaleFactor + halfGap;
            if (_tmpSize > _legendItemHeight)
            {
                _legendItemHeight = _tmpSize;
            }
            float totLegHeight = (float)Math.Ceiling((double)numberOfCurvesToDraw / (double)_numberOfColumns)
                                 * _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 (numberOfCurvesToDraw > 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;
        }
Пример #20
0
		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>
        /// 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;
        }
Пример #22
0
		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;
		}
Пример #23
0
        /// <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="GraphPane.AxisRect"/> 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="tAxisRect">
        /// The rectangle that contains the area bounded by the axes, in pixel units.
        /// <seealso cref="GraphPane.AxisRect">AxisRect</seealso>
        /// </param>
        public void CalcRect(Graphics g, PaneBase pane, float scaleFactor,
                             ref RectangleF tAxisRect)
        {
            // Start with an empty rectangle
            this.rect             = Rectangle.Empty;
            this.hStack           = 1;
            this.legendItemWidth  = 1;
            this.legendItemHeight = 0;

            // If the legend is invisible, don't do anything
            if (!this.isVisible)
            {
                return;
            }

            int   nCurve         = 0;
            float charHeight     = this.FontSpec.GetHeight(scaleFactor),
                  halfCharHeight = charHeight / 2.0F,
                  charWidth      = this.FontSpec.GetWidth(g, scaleFactor),
                  maxWidth       = 0,
                  tmpWidth;

            PaneList paneList = GetPaneList(pane);

            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)
                {
                    if (curve.Label != "" && curve.IsLegendLabelVisible)
                    {
                        // Calculate the width of the label save the max width

                        tmpWidth = this.FontSpec.GetWidth(g, curve.Label, scaleFactor);

                        if (tmpWidth > maxWidth)
                        {
                            maxWidth = tmpWidth;
                        }

                        // Save the maximum symbol height for line-type curves
                        if (curve is LineItem && ((LineItem)curve).Symbol.Size > this.legendItemHeight)
                        {
                            this.legendItemHeight = ((LineItem)curve).Symbol.Size;
                        }

                        nCurve++;
                    }
                }
                if (pane is MasterPane && ((MasterPane)pane).HasUniformLegendEntries)
                {
                    break;
                }
            }

            float widthAvail;

            // Is this legend horizontally stacked?

            if (this.isHStack)
            {
                // Determine the available space for horizontal stacking
                switch (this.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 = tAxisRect.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 = tAxisRect.Width / 2;
                    break;

                // shouldn't ever happen
                default:
                    widthAvail = 0;
                    break;
                }

                // width of one legend entry
                this.legendItemWidth = 3 * charHeight + 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)
                {
                    this.hStack = (int)((widthAvail - halfCharHeight) / this.legendItemWidth);
                }

                // You can never have more columns than legend entries
                if (this.hStack > nCurve)
                {
                    this.hStack = nCurve;
                }

                // a saftey check
                if (this.hStack == 0)
                {
                    this.hStack = 1;
                }
            }
            else
            {
                this.legendItemWidth = 3.5F * charHeight + 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 = this.hStack * this.legendItemWidth;

            // The total legend height
            this.legendItemHeight = this.legendItemHeight * (float)scaleFactor + halfCharHeight;
            if (charHeight > this.legendItemHeight)
            {
                this.legendItemHeight = charHeight;
            }
            float totLegHeight = (float)Math.Ceiling((double)nCurve / (double)hStack)
                                 * this.legendItemHeight;

            RectangleF newRect = new RectangleF();

            // Now calculate the legend rect based on the above determined parameters
            // Also, adjust the axisRect 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 axisRect
                // as required.  The right and bottom edges are calculated at the bottom of the switch.
                switch (this.position)
                {
                case LegendPos.Right:
                    newRect.X = pane.PaneRect.Right - totLegWidth - pane.MarginRight * (float)scaleFactor;
                    newRect.Y = tAxisRect.Top;

                    tAxisRect.Width -= totLegWidth + halfCharHeight;
                    break;

                case LegendPos.Top:
                    newRect.X = tAxisRect.Left;
                    newRect.Y = tAxisRect.Top;

                    tAxisRect.Y      += totLegHeight + halfCharHeight;
                    tAxisRect.Height -= totLegHeight + halfCharHeight;
                    break;

                case LegendPos.TopCenter:
                    newRect.X = tAxisRect.Left + (tAxisRect.Width - totLegWidth) / 2;
                    newRect.Y = tAxisRect.Top;

                    tAxisRect.Y      += totLegHeight + halfCharHeight;
                    tAxisRect.Height -= totLegHeight + halfCharHeight;
                    break;

                case LegendPos.Bottom:
                    newRect.X = tAxisRect.Left + (tAxisRect.Width - totLegWidth) / 2;
                    newRect.Y = pane.PaneRect.Bottom - totLegHeight - pane.MarginBottom * (float)scaleFactor;

                    tAxisRect.Height -= totLegHeight + halfCharHeight;
                    break;

                case LegendPos.BottomCenter:
                    newRect.X = tAxisRect.Left + (tAxisRect.Width - totLegWidth) / 2;
                    newRect.Y = tAxisRect.Bottom;

                    tAxisRect.Height -= totLegHeight + halfCharHeight;
                    break;

                case LegendPos.Left:
                    newRect.X = pane.PaneRect.Left + pane.MarginLeft * (float)scaleFactor;
                    newRect.Y = tAxisRect.Top;

                    tAxisRect.X     += totLegWidth + halfCharHeight;
                    tAxisRect.Width -= totLegWidth + halfCharHeight;
                    break;

                case LegendPos.InsideTopRight:
                    newRect.X = tAxisRect.Right - totLegWidth;
                    newRect.Y = tAxisRect.Top;
                    break;

                case LegendPos.InsideTopLeft:
                    newRect.X = tAxisRect.Left;
                    newRect.Y = tAxisRect.Top;
                    break;

                case LegendPos.InsideBotRight:
                    newRect.X = tAxisRect.Right - totLegWidth;
                    newRect.Y = tAxisRect.Bottom - totLegHeight;
                    break;

                case LegendPos.InsideBotLeft:
                    newRect.X = tAxisRect.Left;
                    newRect.Y = tAxisRect.Bottom - totLegHeight;
                    break;

                case LegendPos.Float:
                    newRect.Location = this.Location.TransformTopLeft(pane, totLegWidth, totLegHeight);
                    break;
                }
            }

            this.rect = newRect;
        }
        /// <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;

            InitLayout();
        }
Пример #25
0
        private float GetMaxHeight(PaneList paneList, Graphics g, float scaleFactor)
        {
            // Set up some scaled dimensions for calculating sizes and locations
            float charHeight = FontSpec.GetHeight(scaleFactor);

            // 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 &&
                        curve._label._fontSpec != null)
                    {
                        float tmpHeight = curve._label._fontSpec.GetHeight(scaleFactor);
                        if (tmpHeight > charHeight)
                            charHeight = tmpHeight;
                    }
                }
            }

            return charHeight;
        }
        /// <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[] ) );
        }
        /// <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)
        {
            scaleFactor = Math.Min(scaleFactor, 1F * (g.DpiX / 72.0f));
            // if the legend is not visible, do nothing
            if (!_isVisible)
            {
                return;
            }

            Region     oldClip  = g.Clip;
            RectangleF clipRect = new RectangleF(_rect.X, _rect.Y, _rect.Width, _rect.Height);

            clipRect.Inflate(1, 1);
            g.SetClip(clipRect);
            // 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
            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)
                {
                    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;

                        tmpFont.Draw(g, pane.IsPenWidthScaled, 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);

                        // maintain a curve count for positioning
                        iEntry++;
                    }
                }
                if (pane is MasterPane && ((MasterPane)pane).IsUniformLegendEntries)
                {
                    break;
                }
            }

            clipRect.Inflate(2, 2);
            g.SetClip(clipRect);
            clipRect.Inflate(-1, -1);
            // Draw a border around the legend if required
            if (iEntry > 0)
            {
                this.Border.Draw(g, pane.IsPenWidthScaled, scaleFactor, clipRect);
            }

            g.SetClip(oldClip, System.Drawing.Drawing2D.CombineMode.Replace);
        }