///<summary>Adds the specified section to the collection, but not to the end.  Instead, it inserts it exactly where it belongs based on the type.  The order cannot be changed by the user. Returns the index at which the section has been added, or -1 if not allowed because it already exists.</summary>
		public int Add(Section value){
			//if(value.Kind==AreaSectionKind.GroupHeader);
			//if(value.Kind==AreaSectionKind.GroupFooter);
			if(List.Count==0){
				List.Add(value);
				return 0;
			}
			for(int i=0;i<List.Count;i++){
				//we are trying to find the item to insert before
				if(i==List.Count-1){//if last item in list, then only option is to add to end of list
					List.Insert(i,value);
					return i;
				}
				if((int)value.Kind < (int)((Section)List[i]).Kind){
					List.Insert(i,value);
					return i;
				}
			}
			return -1;
		}
		///<summary></summary>
		public int IndexOf(Section value){
			return(List.IndexOf(value));
		}
 ///<summary>Prints one section other than details at the specified x and y position on the page.  The math to decide whether it will fit on the current page is done ahead of time. There is no mechanism for splitting a section across multiple pages.</summary>
 private void PrintSection(Graphics g,Section section,int xPos,int yPos)
 {
     ReportObject textObject;
     ReportObject fieldObject;
     //LineObject lineObject;
     //BoxObject boxObject;
     StringFormat strFormat;//used each time text is drawn to handle alignment issues
     //string rawText="";//the raw text for a given field as taken from the database
     string displayText="";//The formatted text to print
     foreach(ReportObject reportObject in MyReport.ReportObjects){
         //todo later: check for lines and boxes that span multiple sections.
         if(reportObject.SectionName!=section.Name){
             continue;
         }
         if(reportObject.ObjectKind==ReportObjectKind.TextObject){
             textObject=reportObject;
             strFormat=ReportObject.GetStringFormat(textObject.TextAlign);
             RectangleF layoutRect=new RectangleF(xPos+textObject.Location.X
                 ,yPos+textObject.Location.Y
                 ,textObject.Size.Width,textObject.Size.Height);
             g.DrawString(textObject.StaticText,textObject.Font,Brushes.Black,layoutRect,strFormat);
         }
         else if(reportObject.ObjectKind==ReportObjectKind.FieldObject){
             fieldObject=reportObject;
             strFormat=ReportObject.GetStringFormat(fieldObject.TextAlign);
             RectangleF layoutRect=new RectangleF(xPos+fieldObject.Location.X
                 ,yPos+fieldObject.Location.Y
                 ,fieldObject.Size.Width,fieldObject.Size.Height);
             displayText="";
             if(fieldObject.FieldKind==FieldDefKind.SummaryField){
                 displayText=fieldObject.GetSummaryValue
                     (MyReport.ReportTable,MyReport.DataFields.IndexOf
                     (fieldObject.SummarizedField))
                     .ToString(fieldObject.FormatString);
             }
             else if(fieldObject.FieldKind==FieldDefKind.SpecialField){
                 if(fieldObject.SpecialType==SpecialFieldType.PageNofM){//not functional yet
                     //displayText=Lan.g(this,"Page")+" "+(pagesPrinted+1).ToString()
                     //	+Lan.g(
                 }
                 else if(fieldObject.SpecialType==SpecialFieldType.PageNumber){
                     displayText=Lan.g(this,"Page")+" "+(pagesPrinted+1).ToString();
                 }
             }
             g.DrawString(displayText,fieldObject.Font,Brushes.Black,layoutRect,strFormat);
         }
         //incomplete: else if lines
         //incomplete: else if boxes.
     }//foreach reportObject
     //sectionsPrinted=sectionIndex+1;//mark current section as printed.
     //MessageBox.Show(pagesPrinted.ToString()+","+sectionsPrinted.ToString());
     //yPos+=section.Height;//set current yPos to the bottom of the section just printed.
 }
        ///<summary>Prints some rows of the details section at the specified x and y position on the page.  The math to decide how many rows to print is done ahead of time.  The number of rows printed so far is kept global so that it can be used in calculating the layout of this section.</summary>
        private void PrintDetailsSection(Graphics g,Section section,int xPos,int yPos,int rowsToPrint)
        {
            ReportObject textObject;
            ReportObject fieldObject;
            //LineObject lineObject;
            //BoxObject boxObject;
            StringFormat strFormat;//used each time text is drawn to handle alignment issues
            string rawText="";//the raw text for a given field as taken from the database
            string displayText="";//The formatted text to print
            string prevDisplayText="";//The formatted text of the previous row. Used to test suppress dupl.
            //loop through each row in the table
            for(int i=rowsPrinted;i<rowsPrinted+rowsToPrint;i++){
                foreach(ReportObject reportObject in MyReport.ReportObjects){
                    //todo later: check for lines and boxes that span multiple sections.
                    if(reportObject.SectionName!=section.Name){
                        //skip any reportObjects that are not in this section
                        continue;
                    }
                    if(reportObject.ObjectKind==ReportObjectKind.TextObject){
                        //not typical to print textobject in details section, but allowed
                        textObject=reportObject;
                        strFormat=ReportObject.GetStringFormat(textObject.TextAlign);
                        RectangleF layoutRect=new RectangleF(xPos+textObject.Location.X
                            ,yPos+textObject.Location.Y
                            ,textObject.Size.Width,textObject.Size.Height);
                        g.DrawString(textObject.StaticText,textObject.Font
                            ,new SolidBrush(textObject.ForeColor),layoutRect,strFormat);
                    }
                    else if(reportObject.ObjectKind==ReportObjectKind.FieldObject){
                        fieldObject=reportObject;
                        strFormat=ReportObject.GetStringFormat(fieldObject.TextAlign);
                        RectangleF layoutRect=new RectangleF(xPos+fieldObject.Location.X,yPos+fieldObject.Location.Y,fieldObject.Size.Width,fieldObject.Size.Height);
                        if(fieldObject.FieldKind==FieldDefKind.DataTableField){
                            rawText=MyReport.ReportTable.Rows
                                [i][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString();
                            displayText=rawText;
                            if(fieldObject.ValueType==FieldValueType.Age){
                                displayText=Patients.AgeToString(Patients.DateToAge(PIn.Date(MyReport.ReportTable.Rows[i][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString())));//(fieldObject.FormatString);
                            }
                            else if(fieldObject.ValueType==FieldValueType.Boolean){
                                displayText=PIn.Bool(MyReport.ReportTable.Rows[i][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString();//(fieldObject.FormatString);
                                if(i>0 && fieldObject.SuppressIfDuplicate){
                                    prevDisplayText=PIn.Bool(MyReport.ReportTable.Rows[i-1][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString();
                                }
                            }
                            else if(fieldObject.ValueType==FieldValueType.Date){
                                displayText=PIn.DateT(MyReport.ReportTable.Rows[i][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString(fieldObject.FormatString);
                                if(i>0 && fieldObject.SuppressIfDuplicate){
                                    prevDisplayText=PIn.DateT(MyReport.ReportTable.Rows[i-1][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString(fieldObject.FormatString);
                                }
                            }
                            else if(fieldObject.ValueType==FieldValueType.Integer){
                                displayText=PIn.Long(MyReport.ReportTable.Rows[i][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString(fieldObject.FormatString);
                                if(i>0 && fieldObject.SuppressIfDuplicate){
                                    prevDisplayText=PIn.Long(MyReport.ReportTable.Rows[i-1][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString(fieldObject.FormatString);
                                }
                            }
                            else if(fieldObject.ValueType==FieldValueType.Number){
                                displayText=PIn.Double(MyReport.ReportTable.Rows[i][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString(fieldObject.FormatString);
                                if(i>0 && fieldObject.SuppressIfDuplicate){
                                    prevDisplayText=PIn.Double(MyReport.ReportTable.Rows[i-1][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString()).ToString(fieldObject.FormatString);
                                }
                            }
                            else if(fieldObject.ValueType==FieldValueType.String){
                                displayText=rawText;
                                if(i>0 && fieldObject.SuppressIfDuplicate){
                                    prevDisplayText=MyReport.ReportTable.Rows[i-1][MyReport.DataFields.IndexOf(fieldObject.DataField)].ToString();
                                }
                            }
                            //suppress if duplicate:
                            if(i>0 && fieldObject.SuppressIfDuplicate && displayText==prevDisplayText){
                                displayText="";
                            }
                        }
                        else if(fieldObject.FieldKind==FieldDefKind.FormulaField){
                            //can't do formulas yet
                        }
                        else if(fieldObject.FieldKind==FieldDefKind.SpecialField){

                        }
                        else if(fieldObject.FieldKind==FieldDefKind.SummaryField){

                        }
                        g.DrawString(displayText,fieldObject.Font
                            ,new SolidBrush(fieldObject.ForeColor),layoutRect,strFormat);
                    }
                    //incomplete: else if lines
                    //incomplete: else if boxes.
                }//foreach reportObject
                yPos+=section.Height;
            }//for i rows
            rowsPrinted+=rowsToPrint;
        }