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; }
public virtual bool AddChild(Balloon generatedBalloon, bool isFromStatic, bool staticDockedBottomFlag) { return false; }
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; }
public bool GetNewRect(Balloon generatedBalloon, ref RectangleNormal outRect) { return this.GetNewRectRightBottom(generatedBalloon, ref outRect); }
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; }
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; }
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); } }
/// <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; }
/// <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 }
/// <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; }
/// <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); } } }
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; }