Esempio n. 1
0
        public override bool AddChild(Balloon generatedBalloon, bool isFromStatic, bool staticDockedBottomFlag)
        {
            RectangleNormal newRect = new RectangleNormal();

            if(isFromStatic)
            {
                // add it to the list
                this.AddChildToList(generatedBalloon);
            }
            else
            {
                if(!this.GetNewRect(generatedBalloon, ref newRect))
                {
                    return false;
                }
                else
                {
                    generatedBalloon.WidthInPixels = newRect.right - newRect.left;
                    generatedBalloon.HeightInPixels = newRect.bottom - newRect.top;
                    generatedBalloon.positionRect.top = newRect.top;
                    generatedBalloon.positionRect.left = newRect.left;
                    generatedBalloon.containerRect = newRect;
                    this.AddChildToList(generatedBalloon);
                }

                // 1. ask for free space and get new rect for it
                // 2. in case there is no space
                //       check for conditions to grow
                //          try to grow this balloon (also parents). Return which one failed growing if anyone failed and return FALSE
                //          if balloon grew goto 1.
                //		if cannot grow return false
                // 3. in case there is enough space.
                //		move new balloon to the rect position and set position and sizes to structure
                //	    add balloon to rect List and return true.
            }
            return true;
        }
Esempio n. 2
0
 public virtual bool AddChild(Balloon generatedBalloon, bool isFromStatic, bool staticDockedBottomFlag)
 {
     return false;
 }
Esempio n. 3
0
        public void AddChildToList(Balloon generatedBalloon)
        {
            // add to rect matrix this rectangle
            generatedBalloon.positionRect.right = generatedBalloon.positionRect.left + generatedBalloon.WidthInPixels;
            generatedBalloon.positionRect.bottom = generatedBalloon.positionRect.top + generatedBalloon.HeightInPixels;
            generatedBalloon.LocationInUnitsX = UnitsManager.Instance.ConvertUnit(generatedBalloon.positionRect.left, MeasureUnits.pixel, generatedBalloon.MeasureUnit);
            generatedBalloon.LocationInUnitsY = UnitsManager.Instance.ConvertUnit(generatedBalloon.positionRect.top, MeasureUnits.pixel, generatedBalloon.MeasureUnit);

            this.rectMatrix.Add(generatedBalloon.positionRect);

            // add parent/child connections
            generatedBalloon.Parent = this;
        }
Esempio n. 4
0
 public bool GetNewRect(Balloon generatedBalloon, ref RectangleNormal outRect)
 {
     return this.GetNewRectRightBottom(generatedBalloon, ref outRect);
 }
Esempio n. 5
0
        public bool GetNewRectRightBottom(Balloon generatedBalloon, ref RectangleNormal outRect)
        {
            RectangleNormal resRect = new RectangleNormal();
            RectangleNormal containRect = new RectangleNormal();
            //RectangleNormal firstFound = null;
            //IEnumerator<RectangleNormal> tempEnum = null;
            //RectangleNormal tempRect;
            ////RectangleNormal intersectFound = null;
            //RectangleNormal maxXRect = null;
            //RectangleNormal minXRect = null;
            //RectangleNormal minYRect = null;

            //bool tmpB = false;

            // make rect to be at 0,0 position. 0,0 is top, left coordinate in this situation
            if(outRect == null)
            {
                return false;
            }

            resRect.left = 0;
            resRect.top = 0;
            resRect.right = generatedBalloon.WidthInPixels;
            resRect.bottom = generatedBalloon.HeightInPixels;

            containRect.left = 0;
            containRect.top = 0;
            containRect.right = this.WidthInPixels;
            containRect.bottom = this.HeightInPixels;
            //System.IO.TextWriter writer;

            // make grid from rectMatrix
            GeneratorGridCell[,] grid;

            int rowCount = 0;
            int colCount = 0;

            List<float> horizLines = new List<float>();
            List<float> vertLines = new List<float>();

            vertLines.Add(0.0f);
            vertLines.Add(containRect.right);
            horizLines.Add(0.0f);
            horizLines.Add(containRect.bottom);

            // Make rect lines
            foreach(RectangleNormal rect in this.rectMatrix)
            {
                // add to horiz lines
                if (!horizLines.Contains(rect.top))
                {
                    horizLines.Add(rect.top);
                }
                if (!horizLines.Contains(rect.bottom))
                {
                    horizLines.Add(rect.bottom);
                }
                // add vertical lines
                if (!vertLines.Contains(rect.left))
                {
                    vertLines.Add(rect.left);
                }
                if (!vertLines.Contains(rect.right))
                {
                    vertLines.Add(rect.right);
                }
            }

            colCount = vertLines.Count - 1;
            rowCount = horizLines.Count - 1;

            vertLines.Sort();
            horizLines.Sort();

            if (rowCount <= 0 || colCount <= 0)
            {
                resRect.MoveTo(0, 0);
                outRect.left = resRect.left;
                outRect.right = resRect.right;
                outRect.bottom = resRect.bottom;
                outRect.top = resRect.top;
                return true;
            }

            grid = new GeneratorGridCell[rowCount, colCount];

            // fill grid
            foreach (RectangleNormal rect in this.rectMatrix)
            {
                int xind1 = vertLines.IndexOf(rect.left);
                int xind2 = vertLines.IndexOf(rect.right);
                int yind1 = horizLines.IndexOf(rect.top);
                int yind2 = horizLines.IndexOf(rect.bottom);

                for(int i = xind1; i < xind2; i++)
                {
                    for(int j = yind1; j < yind2; j++)
                    {
                        grid[j, i].allocated = true;
                    }
                }
            }

            // make coordinates
            for (int i = 0; i < rowCount; i++)
            {
                for (int j = 0; j < colCount; j++)
                {
                    grid[i, j].sx = vertLines[j];
                    grid[i, j].sy = horizLines[i];
                }
            }

            // if all rects all allocated then outRect should be set to bottom line
            bool allAlocated = true;
            for (int i = 0; i < rowCount; i++)
            {
                for (int j = 0; j < colCount; j++)
                {
                    if (!grid[i, j].allocated)
                    {
                        allAlocated = false;
                        break;
                    }
                }
            }

            if (allAlocated)
            {
                // move this to bottom line in case all blocks are allocated
                resRect.left = 0;
                resRect.top = containRect.bottom;
                resRect.right = generatedBalloon.WidthInPixels;
                resRect.bottom = generatedBalloon.HeightInPixels;
            }
            else
            {
                // find first empty place for new rect
                for (int i = 0; i < rowCount; i++)
                {
                    for (int j = 0; j < colCount; j++)
                    {
                        if (!grid[i, j].allocated)
                        {
                            // check if rect can be fitted here
                            resRect.MoveTo(grid[i, j].sx, grid[i, j].sy);
                            // check for any intersection with any rect
                            bool anyIntersection = false;
                            foreach (RectangleNormal tmpRect in this.rectMatrix)
                            {
                                if (tmpRect.Intersect(resRect))
                                {
                                    anyIntersection = true;
                                    break;
                                }
                            }

                            if (!anyIntersection && containRect.Contains(resRect))
                            {
                                outRect.left = resRect.left;
                                outRect.right = resRect.right;
                                outRect.bottom = resRect.bottom;
                                outRect.top = resRect.top;
                                return true;
                            }
                        }
                    }
                }
            }

            if (Math.Abs(resRect.bottom - containRect.bottom) < Epsilon ||
                resRect.bottom < containRect.bottom)
            {
                outRect.left = resRect.left;
                outRect.top = containRect.bottom;
                outRect.right = resRect.right;
                outRect.bottom = containRect.bottom + generatedBalloon.heightInPixels;
            }
            else
            {
                // make output as we are interested in last free position
                outRect.left = resRect.left;
                outRect.right = resRect.right;
                outRect.bottom = resRect.bottom;
                outRect.top = resRect.top;
            }
            return false;
        }
Esempio n. 6
0
        public bool GrowBalloon(Balloon generatedBalloon, float growDelta)
        {
            RectangleNormal rect1 = new RectangleNormal();
            RectangleNormal rect2 = new RectangleNormal();

            Debug.Assert(growDelta >= -Epsilon , "Grow Delta Should never be negative");

            // check what generate algorithm is used and do logic from that
            //if (generatedBalloon->generatingAlgorithm == GENERATING_ALGORITHM_RIGHT_BOTTOM)
            {
                // this means we can grow only on bottom. growDelta contains info how much we need to grow
                // 1. Grow Parent if can grow
                if(this.Parent != null)
                {
                    // check if parent needs to grow at all
                    // rect of parent
                    rect1.top = 0;
                    rect1.left = 0;
                    rect1.right = this.Parent.WidthInPixels;
                    rect1.bottom = this.Parent.HeightInPixels;

                    //desired rect after growth. Growth to allow generatedBalloon to fall in
                    rect2.left = this.positionRect.left;
                    rect2.top = this.positionRect.top;
                    rect2.bottom = (rect2.top + this.HeightInPixels + growDelta);
                    rect2.right = (rect2.left + this.WidthInPixels);

                    if(rect1.Contains(rect2))
                    {
                        // check if we intersect some rectangle in rectMatrix and in case we do return false
                        foreach(RectangleNormal rect in this.Parent.rectMatrix)
                        {
                            // if rect.top != rect2.top && rect.left != rect2.left - or if this is not the same rect which already has taken place
                            // and if it does insterest something return false
                            if (!(System.Math.Abs(rect.top - rect2.top) < Epsilon &&
                                System.Math.Abs(rect.left - rect2.left) < Epsilon) &&
                                rect.Intersect(rect2))
                            {
                                return false;
                            }
                        }

                        // we don't need to grow parent just increase size of self
                        this.HeightInPixels += growDelta;
                        this.containerRect.bottom += growDelta;
                    }
                    else
                    {
                        // can parent grow at all
                        if(this.CanGrow)
                        {
                            // grow parent
                            if(this.Parent is Balloon)
                            {
                                Balloon parentBallon = (Balloon)this.Parent;
                                if(parentBallon.CanGrow && parentBallon.GrowBalloon(generatedBalloon, growDelta))
                                {
                                    this.HeightInPixels += growDelta;
                                    this.containerRect.bottom += growDelta;
                                }
                                else
                                {
                                    return false;
                                }
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else
                        {
                            // cannot increase size return FALSE
                            return false;
                        }
                    }
                }
                else
                {
                    // no parent ... grow in height by required size.
                    this.HeightInPixels += growDelta;
                    this.containerRect.bottom += growDelta;
                }

                this.positionRect.bottom = rect2.bottom;
            }
            //if (generatedBalloon->generatingAlgorithm == GENERATING_ALGORITHM_BOTTOM_RIGHT)
            //{
            //    // this means we can grow only on left
            //    // TODO: Not implemented yet
            //}

            return true;
        }
Esempio n. 7
0
        public void Draw(Balloon parent, Graphics gc)
        {
            float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f;

            switch(this.Type)
            {
                case BorderTypes.TOP_BORDER:
                    x1 = 0;
                    y1 = 0;
                    x2 = parent.WidthInPixels;
                    y2 = y1;
                    x1 -= parent.Borders.left.Enabled ? parent.Borders.left.LineWidth / 2.0f : 0.0f;
                    x2 += parent.Borders.right.Enabled ? parent.Borders.right.LineWidth / 2.0f : 0.0f;
                    break;
                case BorderTypes.LEFT_BORDER:
                    x1 = 0;
                    y1 = 0;
                    x2 = x1;
                    y2 = parent.HeightInPixels;
                    y1 -= parent.Borders.top.Enabled ? parent.Borders.top.LineWidth / 2.0f : 0.0f;
                    y2 += parent.Borders.bottom.Enabled ? parent.Borders.bottom.LineWidth / 2.0f : 0.0f;
                    break;
                case BorderTypes.BOTTOM_BORDER:
                    x1 = 0;
                    y1 = parent.HeightInPixels;
                    x2 = parent.WidthInPixels;
                    y2 = y1;
                    x1 -= parent.Borders.left.Enabled ? parent.Borders.left.LineWidth / 2.0f : 0.0f;
                    x2 += parent.Borders.right.Enabled ? parent.Borders.right.LineWidth / 2.0f : 0.0f;
                    break;
                case BorderTypes.RIGHT_BORDER:
                    x1 = parent.WidthInPixels;
                    y1 = 0;
                    x2 = x1;
                    y2 = parent.HeightInPixels;
                    y1 -= parent.Borders.top.Enabled ? parent.Borders.top.LineWidth / 2.0f : 0.0f;
                    y2 += parent.Borders.bottom.Enabled ? parent.Borders.bottom.LineWidth / 2.0f : 0.0f;
                    break;
            }

            if(this.Enabled)
            {
                gc.Transform = parent.LastDrawMatrix;
                gc.DrawLine(line, x1, y1, x2, y2);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Adds new child to this balloon and performs resize if necessary.
        ///  
        /// </summary>
        /// <param name="generatedBalloon">newly created balloon that needs to fit into this one</param>
        /// <param name="staticBalloonFlag">this flag is true if generated balloon should be threated as static. if true
        /// then it is put exactly where it should be. If this is true staticDockedBottomFlag is ignored</param>
        /// <param name="staticDockedBottomFlag">Flag that tells if this should be threated as static bottom docked ballooon. </param>
        /// <returns></returns>
        public override bool AddChild(Balloon generatedBalloon, bool staticBalloonFlag, bool staticDockedBottomFlag)
        {
            RectangleNormal newRect = new RectangleNormal();

            if(staticBalloonFlag)
            {
                // add it to the list
                this.AddChildToList(generatedBalloon);
            }
            else
            {
                // if there is no room for another child here
                if (this.FillCapacity > 0 && (this.DynamicChildBalloons + 1 > this.FillCapacity) && !staticDockedBottomFlag)
                {
                    return false;
                }

                if(!this.GetNewRect(generatedBalloon, ref newRect))
                {
                    if(this.CanGrow)
                    {
                        // we established that balloon need to grow to put this new one inside and determined ammount of grow
                        // we need to check if grow is allowed on parents side (maybe it is already taken on parents size and allocated in
                        // rect matrix. this is checked before grow
                        if(this.GrowBalloon(generatedBalloon, generatedBalloon.HeightInPixels - (this.HeightInPixels - newRect.top)))
                        {
                            return this.AddChild(generatedBalloon, staticBalloonFlag, staticDockedBottomFlag);
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    if (staticDockedBottomFlag && !this.FitToContent)
                    {
                        // in case this one is static docked bottom and we wont to put him on the bottom of this balloon
                        newRect.top = this.containerRect.bottom - (newRect.bottom - newRect.top);
                        newRect.bottom = this.containerRect.bottom;

                        generatedBalloon.WidthInPixels = newRect.right - newRect.left;
                        generatedBalloon.HeightInPixels = newRect.bottom - newRect.top;
                        generatedBalloon.positionRect.top = newRect.top;
                        generatedBalloon.positionRect.left = newRect.left;
                        generatedBalloon.containerRect = newRect;
                    }
                    else
                    {
                        generatedBalloon.WidthInPixels = newRect.right - newRect.left;
                        generatedBalloon.HeightInPixels = newRect.bottom - newRect.top;
                        generatedBalloon.positionRect.top = newRect.top;
                        generatedBalloon.positionRect.left = newRect.left;
                        generatedBalloon.containerRect = newRect;
                    }
                    this.AddChildToList(generatedBalloon);

                }

                // 1. ask for free space and get new rect for it
                // 2. in case there is no space
                //       check for conditions to grow
                //          try to grow this balloon (also parents). Return which one failed growing if anyone failed and return FALSE
                //          if balloon grew goto 1.
                //		if cannot grow return false
                // 3. in case there is enough space.
                //		move new balloon to the rect position and set position and sizes to structure
                //	    add balloon to rect List and return true.
            }
            return true;
        }
Esempio n. 9
0
        /// <summary>
        /// Write balloon, make its coordinates and draw all child items like static texts, dynamic texts, etc.        /// 
        /// </summary>
        /// <param name="balloon">current ballon that should be used as template for creating new one</param>
        /// <param name="page">current page</param>
        /// <param name="parentBalloon">parent ballon in which this new one should be stored</param>
        /// <param name="isStaticBalloon">is new ballon of static type, meaning that it will be placed where put</param>
        /// <param name="level">just level of recursion parameter</param>
        /// <param name="drawChildren">should this method draw items in ballon or just allocate space</param>
        /// <param name="staticBottomDockedFlag">This flag is set if this should create static Bottom docked balloon</param>
        /// <returns>newly created balloon that should be placed on page</returns>
        Balloon WriteBalloon(Balloon balloon, ReportPage page, Balloon parentBalloon, 
            bool isStaticBalloon, bool drawChildren, bool staticBottomDockedFlag,
            int level)
        {
            string logTab = "";
            for (int i = 0; i < level; i++)
            {
                logTab += "\t";
            }

            Loger.LogMessage(logTab + "WriteBalloon Begin");

            StaticBalloon newStaticBalloon;
            DynamicBalloon newDynamicBalloon;
            UnitsManager unitConverter;

            unitConverter = UnitsManager.Instance;

            // if this balloon is static then place it exactly where it should go
            if (isStaticBalloon)
            {
                newStaticBalloon = (StaticBalloon)CreateNewBalloon(balloon, page, parentBalloon, isStaticBalloon);

                // we don't check if static balloons fall inside parents as they should always be included. Just allocate space for it in parent
                if(parentBalloon != null)
                {
                    parentBalloon.AddChild(newStaticBalloon, true, false);
                    if (drawChildren)
                    {
                        AddNonBalloonChildren(balloon, newStaticBalloon);
                    }
                }
                else
                {
                    page.AddChild(newStaticBalloon, true, false);
                    if (drawChildren)
                    {
                        AddNonBalloonChildren(balloon, newStaticBalloon);
                    }
                }

                Loger.LogMessage(logTab + "WriteBalloon End - return static balloon");
                return newStaticBalloon;
            }
            else
            {
                newDynamicBalloon = (DynamicBalloon)CreateNewBalloon(balloon, page, parentBalloon, isStaticBalloon);

                // in case of dynamic balloons we do next thing
                if(parentBalloon != null)
                {
                    if(!parentBalloon.AddChild(newDynamicBalloon, false, staticBottomDockedFlag))
                    {
                        Loger.LogMessage(logTab + "WriteBalloon End - return NULL - AddChild failed when Parent balloon != null");
                        return null;
                    }
                    else
                    {
                        if (drawChildren)
                        {
                            AddNonBalloonChildren(balloon, newDynamicBalloon);
                        }
                    }
                }
                else
                {
                    //newDynamicBalloon.Parent = EditorController.Instance.EditorProject.ReportPage;
                    //EditorController.Instance.EditorProject.PreviewList.Add(newDynamicBalloon);
                    if(!page.AddChild(newDynamicBalloon, false, false))
                    {
                        Loger.LogMessage(logTab + "WriteBalloon End - return NULL - AddChild failed when Parent balloon == null");
                        return null;
                    }
                    else
                    {
                        if (drawChildren)
                        {
                            AddNonBalloonChildren(balloon, newDynamicBalloon);
                        }
                    }
                }

                Loger.LogMessage(logTab + "WriteBalloon End - return dynamic balloon");
                return newDynamicBalloon;
            }

            //return null;
            // 4.    Make balloon graphically.
            // 5.    For each item in balloon
            // 6.      Process each item and request data when needed by using RequestDataCallback
            // 7.    End
            // do static balloon logic. Static balloons are placed where specified and have static dimensions
        }
Esempio n. 10
0
        /// <summary>
        /// This will create new Balloon object based from Balloon information. 
        /// </summary>
        /// <param name="balloon">Original from what new should be created</param>
        /// <param name="page">Current page</param>
        /// <param name="parentBalloon">parent balloon that is generated</param>
        /// <param name="isStatic">If new balloon should be created as StaticBalloon</param>
        /// <param name="level">level of recursion, for logging purposes</param>
        /// <returns></returns>
        Balloon CreateNewBalloon(Balloon balloon, ReportPage page, Balloon parentBalloon, bool isStatic)
        {
            if (isStatic)
            {
                StaticBalloon newStaticBalloon = new StaticBalloon();
                newStaticBalloon.TemplateBalloon = balloon;
                newStaticBalloon.LocationInUnitsX = balloon.LocationInUnitsX;
                newStaticBalloon.LocationInUnitsY = balloon.LocationInUnitsY;

                newStaticBalloon.WidthInPixels = balloon.GetFitToContentWidthInPixels();
                newStaticBalloon.HeightInPixels = balloon.GetFitToContentHeightInPixels();

                newStaticBalloon.zoomLevel = balloon.zoomLevel;
                newStaticBalloon.sourceBallon = balloon;
                newStaticBalloon.Disabled = true;
                newStaticBalloon.CanGrow = balloon.DockPosition == EditorItem.DockingPosition.DOCK_BOTTOM ? false : balloon.CanGrow;
                newStaticBalloon.Borders = balloon.Borders;
                newStaticBalloon.FillCapacity = balloon.FillCapacity;
                newStaticBalloon.AvailableOnEveryPage = balloon.AvailableOnEveryPage;
                newStaticBalloon.FillingGeneratesNew = balloon.FillingGeneratesNew;
                newStaticBalloon.FitToContent = balloon.FitToContent;
                newStaticBalloon.FillColor = balloon.FillColor;
                newStaticBalloon.MeasureUnit = balloon.MeasureUnit;

                float relLocationX = balloon.LocationInPixelsX; //unitConverter.ConvertUnit(balloon.LocationInUnitsX, balloon.MeasureUnit, MeasureUnits.point);
                float relLocationY = balloon.LocationInPixelsY; //unitConverter.ConvertUnit(balloon.LocationInUnitsY, balloon.MeasureUnit, MeasureUnits.point);
                float width = balloon.GetFitToContentWidthInPixels();
                float height = balloon.GetFitToContentHeightInPixels();

                newStaticBalloon.containerRect.left = relLocationX;
                newStaticBalloon.containerRect.bottom = relLocationY + height;
                newStaticBalloon.containerRect.right = relLocationX + width;
                newStaticBalloon.containerRect.top = relLocationY;
                newStaticBalloon.positionRect.top = relLocationY;
                newStaticBalloon.positionRect.left = relLocationX;
                return newStaticBalloon;
            }
            else
            {
                DynamicBalloon newDynamicBalloon = new DynamicBalloon();
                newDynamicBalloon.FillColor = balloon.FillColor;
                newDynamicBalloon.TemplateBalloon = balloon;
                newDynamicBalloon.LocationInUnitsX = balloon.LocationInUnitsX;
                newDynamicBalloon.LocationInUnitsY = balloon.LocationInUnitsY;
                newDynamicBalloon.zoomLevel = balloon.zoomLevel;
                newDynamicBalloon.sourceBallon = balloon;
                newDynamicBalloon.Disabled = true;
                newDynamicBalloon.FitToContent = balloon.FitToContent;
                newDynamicBalloon.CanGrow = balloon.CanGrow;
                newDynamicBalloon.Borders = balloon.Borders;
                newDynamicBalloon.FillCapacity = balloon.FillCapacity;
                newDynamicBalloon.AvailableOnEveryPage = balloon.AvailableOnEveryPage;
                newDynamicBalloon.FillingGeneratesNew = balloon.FillingGeneratesNew;
                newDynamicBalloon.MeasureUnit = balloon.MeasureUnit;

                newDynamicBalloon.WidthInPixels = balloon.GetFitToContentWidthInPixels();
                newDynamicBalloon.HeightInPixels = balloon.GetFitToContentHeightInPixels();
                newDynamicBalloon.positionRect.top = balloon.LocationInPixelsY;
                newDynamicBalloon.positionRect.left = balloon.LocationInPixelsX;
                return newDynamicBalloon;
            }
            return null;
        }
Esempio n. 11
0
 /// <summary>
 /// Add non balloon children to created balloon. It will copy all items from template to created one
 /// </summary>
 /// <param name="templateBalloon"></param>
 /// <param name="createdBalloon"></param>
 private void AddNonBalloonChildren(Balloon templateBalloon, Balloon createdBalloon)
 {
     foreach(EditorItem tmpItem in templateBalloon.Children)
     {
         if(tmpItem is Balloon)
         {
             //We only copy NonBalloon Items!
             continue;
         }
         else
         {
             EditorItem clone = (EditorItem)tmpItem.SimpleClone();
             clone.Parent = createdBalloon;
             clone.Disabled = true;
             //createdBalloon.Children.Add(clone);
         }
     }
 }
Esempio n. 12
0
        public GeneratePrivewReturn GeneratePreview(Balloon parentBalloon, Balloon parentGeneratedBalloon, int level)
        {
            string logTab = "";
            for (int i = 0; i < level; i++ )
            {
                logTab += "\t";
            }

            iteratorCounter++;

            Loger.LogMessage(logTab + "Generate Preview " + iteratorCounter.ToString());
            ReportPage sourcePage = EditorController.Instance.EditorProject.SourceReportPage;
            ReportPage currentPage = EditorController.Instance.EditorProject.CurrentReportPage;
            List<EditorItem> balloons;
            List<Balloon> newBottomDockedPageBalloons = new List<Balloon>();
            StaticBalloon newStaticBalloon;
            DynamicBalloon newDynamicBalloon;
            GeneratePrivewReturn genRes;

            if (parentBalloon == null)
            {
                balloons = sourcePage.Children;
            }
            else
            {
                balloons = parentBalloon.Children;
            }

            // generate non-balloon items that are on page
            if (parentBalloon == null)
            {
                foreach (EditorItem tmpItem in balloons)
                {
                    if (!(tmpItem is Balloon))
                    {
                        EditorItem clone = (EditorItem)tmpItem.SimpleClone();
                        clone.Parent = currentPage;
                        clone.Disabled = true;
                        //currentPage.Children.Add(clone);
                    }
                }
            }

            // 1. generate static balloons but ignore bottom docked ones as those need to go after dynamics
            Loger.LogMessage(logTab + "Generate static balloons");
            foreach(EditorItem balloon in balloons)
            {
                // if balloon is top docked and has prev top docked dynamics skip it
                if (balloon is StaticBalloon && balloon.DockPosition == EditorItem.DockingPosition.DOCK_TOP &&
                    (balloon as StaticBalloon).HasDynamicTopBallons)
                {
                    continue;
                }

                // if balloon is Static and docking is bottom and this balloon is placed on page we need to allocate space for it in rectMatrix
                // of page so now one can take this space later.
                if ((balloon is StaticBalloon && balloon.DockPosition == EditorItem.DockingPosition.DOCK_BOTTOM && parentBalloon == null) ||
                    (balloon is StaticBalloon && balloon.DockPosition == EditorItem.DockingPosition.DOCK_BOTTOM && parentBalloon != null && !parentBalloon.CanGrow))
                {
                    // create it as standard static balloon but do not draw children items yet just allocate space for it
                    newStaticBalloon = (StaticBalloon)WriteBalloon((Balloon)balloon, currentPage, parentGeneratedBalloon, true, false, true, level);
                    newBottomDockedPageBalloons.Add(newStaticBalloon);
                }

                // if balloon is Static and docking position is not bottom
                if (balloon is StaticBalloon && balloon.DockPosition != EditorItem.DockingPosition.DOCK_BOTTOM)
                {
                    newStaticBalloon = (StaticBalloon)WriteBalloon((Balloon)balloon, currentPage, parentGeneratedBalloon, true, true, false, level);

                    // 8.    Recursive call to 1. with parent balloon set as this
                    genRes = GeneratePreview((Balloon)balloon, newStaticBalloon, level+1);
                    if(genRes == GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE)
                    {
                        Loger.LogMessage(logTab + "Not enough space");
                    }
                    else if(genRes == GeneratePrivewReturn.GENERATE_BALLOONS_FAILED)
                    {
                        Loger.LogMessage(logTab + "Generate Failed");
                        return genRes;
                    }
                }
            } // foreach static balloon

            // for each dynamic balloon
            Loger.LogMessage(logTab + "Generate dynamic balloons");
            GeneratePrivewReturn result = GeneratePrivewReturn.GENERATE_BALLOONS_OK;

            // 2. generate dynamic balloons
            foreach(EditorItem tmpItem in balloons)
            {
                if(tmpItem is Balloon)
                {
                    Balloon balloon = (Balloon)tmpItem;
                    if(balloon is DynamicBalloon)
                    {
                        int count = 0;
                        int maxItems = AppOptions.Instance.NumOffPreviewItems;

                        while(count < maxItems)
                        {
                            count++;

                            newDynamicBalloon = (DynamicBalloon)WriteBalloon(balloon, currentPage, parentGeneratedBalloon, false, true, false, level);
                            if(newDynamicBalloon == null)
                            {
                                // we failed generating new balloon as not possible to write new one inside parent Generated Balloon. We need new parent.
                                Loger.LogMessage(logTab + "Not enough space");
                                result = GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE;
                                goto ProcessBottomDocked;
                            }

                            // 18.     Recursive call to 1. with parent balloon set as this
                            genRes = GeneratePreview(balloon, newDynamicBalloon, level+1);
                            if(genRes == GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE)
                            {
                                Loger.LogMessage(logTab + "Not enough space2");
                                // we should continue to next iteration without checking condition and reading data
                                continue;
                            }
                            else if(genRes == GeneratePrivewReturn.GENERATE_BALLOONS_FAILED)
                            {
                                Loger.LogMessage(logTab + "Generate Failed");
                                return genRes;
                            }
                        }
                    }
                }
            }

            Loger.LogMessage(logTab + "Generate bottom docked static balloons");

            // 3. generate bottom docked static balloons
            for (int i = balloons.Count - 1; i >= 0; i--)
            {
                EditorItem balloon = balloons[i];

                // if balloon is Static and docking position is bottom
                if (balloon is StaticBalloon && balloon.DockPosition == EditorItem.DockingPosition.DOCK_BOTTOM && parentBalloon != null &&
                    parentBalloon.CanGrow)
                {
                    // write new balloon but handle it as dynamic balloon
                    newDynamicBalloon = (DynamicBalloon)WriteBalloon((Balloon)balloon, currentPage, parentGeneratedBalloon, false, true, true, level);

                    // if this newDynamicBalloon is not generated to be bottom one move it down
                    if (newDynamicBalloon == null)
                    {
                        // we failed generating new balloon as not possible to write new one inside parent Generated Balloon. We need new parent.
                        Loger.LogMessage(logTab + "Not enough space");
                        result = GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE;
                        goto ProcessBottomDocked;
                    }

                    genRes = GeneratePreview((Balloon)balloon, newDynamicBalloon, level + 1);

                    if (genRes == GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE)
                    {
                        Loger.LogMessage(logTab + "Not enough space");
                    }
                    else if (genRes == GeneratePrivewReturn.GENERATE_BALLOONS_FAILED)
                    {
                        Loger.LogMessage(logTab + "Generate Failed");
                        return genRes;
                    }
                }
            } // foreach static balloon docked bottom

            // 4. Generate top docked static balloons
            foreach (EditorItem tmpItem in balloons)
            {
                if (tmpItem is Balloon && tmpItem is StaticBalloon)
                {
                    StaticBalloon balloon = tmpItem as StaticBalloon;
                    if (balloon.DockPosition == EditorItem.DockingPosition.DOCK_TOP && balloon.HasDynamicTopBallons)
                    {
                        // write new balloon but handle it as dynamic balloon
                        newDynamicBalloon = (DynamicBalloon)WriteBalloon((Balloon)balloon, currentPage, parentGeneratedBalloon, false, true, true, level);

                        // if this newDynamicBalloon is not generated to be bottom one move it down
                        if (newDynamicBalloon == null)
                        {
                            // we failed generating new balloon as not possible to write new one inside parent Generated Balloon. We need new parent.
                            Loger.LogMessage(logTab + "Not enough space");
                            result = GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE;
                            goto ProcessBottomDocked;
                        }

                        genRes = GeneratePreview((Balloon)balloon, newDynamicBalloon, level + 1);

                        if (genRes == GeneratePrivewReturn.GENERATE_BALLOONS_NOT_ENOUGH_SPACE)
                        {
                            Loger.LogMessage(logTab + "Not enough space");
                        }
                        else if (genRes == GeneratePrivewReturn.GENERATE_BALLOONS_FAILED)
                        {
                            Loger.LogMessage(logTab + "Generate Failed");
                            return genRes;
                        }
                    }
                }
            }

            // Process Bottom Docked
            ProcessBottomDocked:

            DrawRemainingBalloons(newBottomDockedPageBalloons);

            return result;
        }