private int GetXPosByParentPreviousSibling(OrgChartNode node) { int result = -1; OrgChartNode parentPrevSibling = node.Parent?.PreviousSibling; if (parentPrevSibling != null) { if (parentPrevSibling.Children.Any()) { result = parentPrevSibling.LastChild.Position.X + this.option.BoxWidth + this.option.HorizontalSpace; } else { result = parentPrevSibling.Position.X + this.option.BoxWidth + this.option.HorizontalSpace; } } else //ParentPrevSibling == null { if (!node.IsRoot) { result = GetXPosByParentPreviousSibling(node.Parent); } } return(result); }
public static List <OrgChartNode> ConvertToNodes(OrgChartNode parentNode) { List <OrgChartNode> nodes = new List <OrgChartNode>(); GetChildNodes(parentNode, nodes); return(nodes); }
/// <summary> /// 手柄特殊位置 /// </summary> /// <param name="node"></param> /// <param name="changed"></param> /// <returns></returns> private Rectangle HandleSpeicalPosition(OrgChartNode node, out bool changed) { changed = false; int level = node.Level; bool isOnlyOne = nodes.Where(item => item.Level == level).Count() == 1; if (!this.isSampleTree && isOnlyOne && this.option.UseMinBoxWidthWhenHasOnlyOne && this.option.MinBoxWidth > 0) { node.Position = new Rectangle(node.Position.X + (this.option.BoxWidth - this.option.MinBoxWidth), node.Position.Y, this.option.MinBoxWidth, node.Position.Height); changed = true; } return(node.Position); }
private int GetXPosByOwnChildren(OrgChartNode node) { int result = -1; if (node.Children.Any()) { result = (((node.LastChild.Position.X + this.option.BoxWidth) - node.FirstChild.Position.X) / 2) - (this.option.BoxWidth / 2) + node.FirstChild.Position.X; } return(result); }
private static void GetOrgChartModelChildren(OrgChartNode parentNode, IEnumerable <OrgChartNode> models) { List <OrgChartNode> children = models.Where(item => item.ParentId == parentNode.Id).ToList(); int i = 1; parentNode.Children.AddRange(children); children.ForEach(item => { item.Order = i++; item.Parent = parentNode; item.Level = parentNode.Level + 1; GetOrgChartModelChildren(item, models); }); }
public static OrgChartNode BuildTree(IEnumerable <OrgChartNode> nodes) { OrgChartNode rootNode = nodes.FirstOrDefault(item => string.IsNullOrEmpty(item.ParentId)); if (rootNode != null) { if (rootNode.Children.Any()) { return(rootNode); } rootNode.Level = 0; GetOrgChartModelChildren(rootNode, nodes); } return(rootNode); }
private static List <OrgChartNode> GetChildNodes(OrgChartNode parentNode, List <OrgChartNode> nodes) { if (parentNode != null && !nodes.Any(item => item.Id == parentNode.Id)) { nodes.Add(parentNode); } if (parentNode != null && parentNode.Children.Any()) { nodes.AddRange(parentNode.Children); parentNode.Children.ForEach(item => { GetChildNodes(item, nodes); }); } return(nodes); }
private void CalculatePosition(OrgChartNode node, int y) { foreach (OrgChartNode child in node.Children.OrderBy(item => item.Order)) { this.CalculatePosition(child, y + 1); } int startX; int startY; int margin = this.option.Margin; int[] resultsArr = new int[] { this.GetXPosByOwnChildren(node), this.GetXPosByParentPreviousSibling(node), this.GetXPosByPreviousSibling(node), margin }; Array.Sort(resultsArr); startX = resultsArr[3]; startY = (y * (this.option.BoxHeight + this.option.VerticalSpace)) + margin; int width = this.option.BoxWidth; int height = this.option.BoxHeight; //update the coordinates of this box into the matrix, for later calculations Rectangle drawRect = new Rectangle(startX, startY, width, height); //update the image size if (imgWidth < (startX + width + margin)) { imgWidth = startX + width + margin; } if (imgHeight < (startY + height + margin)) { imgHeight = startY + height + margin; } node.Position = drawRect; }
/// <summary> /// 组织机构图表生成器 /// </summary> /// <param name="nodes"></param> /// <param name="option"></param> public OrgChartGenerator(List <OrgChartNode> nodes, OrgChartOption option) { this.nodes = nodes; if (option != null) { this.option = option; } this.rootNode = OrgChartHelper.BuildTree(this.nodes); int maxLevelNodesCount = (from node in nodes group node by node.Level into gp select new { Level = gp.Key, Count = gp.Count() } ).Max(item => item.Count); this.isSampleTree = maxLevelNodesCount < this.option.SampeTreeLevelCount; if (this.option.UseDefaultIfSampleTree && this.isSampleTree) { this.option = this.DefaultOption; } }
private void generarOrganigrama(RadOrgChart control, List <SPE_OBTIENE_PLAN_VIDA_CARRERA_Result> source, bool ordenar, string tipo) { bool mostrarcheck; string css = ""; int i = 0; if (ordenar) { source = source.OrderByDescending(t => t.NO_NIVEL).ToList(); } if (source.Count > 0) { if (source[i].ID_PUESTO == vIdPuesto) { mostrarcheck = false; switch (tipo) { case "NATURAL": css = "cssNaturalActual"; break; case "ALTER": css = "cssAlternativaActual"; break; case "HOR": css = "cssHorizontalActual"; break; } } else { mostrarcheck = true; switch (tipo) { case "NATURAL": css = "cssNatural"; break; case "ALTER": css = "cssAlternativa"; break; case "HOR": css = "cssHorizontal"; break; } } var node = new OrgChartNode(); node.DataItem = source[i]; var groupItem = new OrgChartGroupItem() { Template = new SelectionTemplate(source[i].ID_PUESTO, source[i].NB_PUESTO, mostrarcheck, css) }; groupItem.CssClass = css; if (source.Count > 1) { generarOrganigrama(source, node, i + 1, tipo); } node.GroupItems.Add(groupItem); control.Nodes.Add(node); } }
private void generarOrganigrama(List <SPE_OBTIENE_PLAN_VIDA_CARRERA_Result> source, OrgChartNode nodo, int i, string tipo) { bool mostrarcheck; string css = ""; if (source[i].ID_PUESTO == vIdPuesto) { mostrarcheck = false; switch (tipo) { case "NATURAL": css = "cssNaturalActual"; break; case "ALTER": css = "cssAlternativaActual"; break; case "HOR": css = "cssHorizontalActual"; break; } } else { mostrarcheck = true; switch (tipo) { case "NATURAL": css = "cssNatural"; break; case "ALTER": css = "cssAlternativa"; break; case "HOR": css = "cssHorizontal"; break; } } var node = new OrgChartNode(); node.DataItem = source[i]; var groupItem = new OrgChartGroupItem() { Template = new SelectionTemplate(source[i].ID_PUESTO, source[i].NB_PUESTO, mostrarcheck, css) }; groupItem.CssClass = css; nodo.Nodes.Add(node); node.GroupItems.Add(groupItem); if (i < source.Count - 1) { generarOrganigrama(source, node, i + 1, tipo); } }
/// <summary> /// Draws the actual chart image. /// </summary> private void DrawChart(OrgChartNode node) { // Create font and brush. Font drawFont = new Font(this.option.FontName, this.option.FontSize); SolidBrush drawBrush = new SolidBrush(this.option.FontColor); Pen boxPen = new Pen(this.option.BoxBorderColor, this.option.BoxBorderWidth); Pen connectLinePen = new Pen(this.option.ConnectLineColor, this.option.ConnectLineWidth); StringFormat drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Center; drawFormat.LineAlignment = StringAlignment.Center; foreach (OrgChartNode child in node.Children.OrderBy(item => item.Order)) { this.DrawChart(child); } //// Create string to draw. String drawString = node.Name; bool changed = false; int boxWidth = this.option.BoxWidth; Rectangle position = this.HandleSpeicalPosition(node, out changed); if (!changed) { #region auto height/width if (this.option.AutoBoxHeight || this.option.AutoBoxWidth) { var height = (int)gr.MeasureString(drawString, drawFont, node.Position.Width).Height; if (height > node.Position.Height) { if (this.option.AutoBoxHeight) { node.Position = new Rectangle(node.Position.X, node.Position.Y, node.Position.Width, height); } else if (this.option.AutoBoxWidth) { int increment = 5; int count = node.Position.Width / increment; for (int i = 1; i <= count; i++) { int width = node.Position.Width + i * increment; height = (int)gr.MeasureString(drawString, drawFont, width).Height; if (height <= node.Position.Height) { node.Position = new Rectangle(node.Position.X + (int)((node.Position.Width - width) / 2), node.Position.Y, width, node.Position.Height); boxWidth = node.Position.Width; break; } } } } } #endregion } else { boxWidth = position.Width; } var overlapNodes = this.nodes.Where(item => node.Level == item.Level && (node.Position.X > item.Position.X && node.Position.X < item.Position.X + item.Position.Width)); if (overlapNodes.Count() > 0) //overlap { OrgChartNode overlapNode = overlapNodes.First(); int overlapWidth = overlapNode.Position.X + overlapNode.Position.Width - node.Position.X; int newX = overlapNode.Position.X + overlapNode.Position.Width + this.option.HorizontalSpace; node.OffsetX = newX - node.Position.X; node.Position = new Rectangle(newX, node.Position.Y, node.Position.Width, node.Position.Height); offsetNodes.Add(node); } else { if (offsetNodes.Any(item => item.ParentId == node.ParentId)) { int offsetX = offsetNodes.FirstOrDefault(item => item.ParentId == node.ParentId).OffsetX; node.Position = new Rectangle(node.Position.X + offsetX, node.Position.Y, node.Position.Width, node.Position.Height); } } gr.DrawRectangle(boxPen, node.Position); gr.FillRectangle(new SolidBrush(this.option.BoxFillColor), node.Position); //String drawString = EmployeeChartData[OrgCharMatrix[x, y]].Position.X.ToString(); // Draw string to screen. gr.DrawString(drawString, drawFont, drawBrush, node.Position, drawFormat); //draw connecting lines if (!node.IsRoot) { //all but the top box should have lines growing out of their top gr.DrawLine(connectLinePen, node.Position.Left + (boxWidth / 2), node.Position.Top, node.Position.Left + (boxWidth / 2), node.Position.Top - (this.option.VerticalSpace / 2)); } if (node.Children.Any()) { //all nodes which have nodes should have lines coming from bottom down gr.DrawLine(connectLinePen, node.Position.Left + (boxWidth / 2), node.Position.Top + this.option.BoxHeight, node.Position.Left + (boxWidth / 2), node.Position.Top + this.option.BoxHeight + (this.option.VerticalSpace / 2)); } if (node.PreviousSibling != null) { //the prev node has the same parent - connect the 2 nodes gr.DrawLine(connectLinePen, node.PreviousSibling.Position.Left + (this.option.BoxWidth / 2) - (this.option.ConnectLineWidth / 2), node.PreviousSibling.Position.Top - (this.option.VerticalSpace / 2), node.Position.Left + (this.option.BoxWidth / 2) + (this.option.ConnectLineWidth / 2), node.Position.Top - (this.option.VerticalSpace / 2)); } }