private void UpdateTabLocations() { int total = 0; Point drawPoint = Point.Empty; switch (owner.Navigator.Location) { case NavigatorLocation.Bottom: drawPoint.Y = pageHeight; break; } if (tabs == null || tabs.Length != owner.VisiblePageCount) { if (visiblePages.Count != owner.VisiblePageCount) { RefreshAllPages(); // return because RefreshAllPages will call this function. return; } tabs = new TabRenderInfo[owner.VisiblePageCount]; for (int i = 0; i < tabs.Length; i++) { tabs[i] = new TabRenderInfo(); } } // calculate the total size used if none of the tabs are compressed. for (int i = 0; i < visiblePages.Count; i++) { TabRenderInfo info = tabs[i]; Size tabSize, imageSize, textSize; TabMetrics(visiblePages[i], out tabSize, out imageSize, out textSize); total += tabSize.Width; info.Location = drawPoint; info.imageSize = imageSize; info.textSize = textSize; if (navProperties.AllowClose && ParentDesign == false) { info.ShowCloseBox = true; } drawPoint.X += tabSize.Width; } if (total >= ClientSize.Width) { int pixelsToReclaim = total - ClientSize.Width + 1; int divideCount = tabs.Length; if (SelectedIndex >= 0 && divideCount > 1) { divideCount -= 1; } int pixelsReclaimed = 0; // remove close boxes first for (int i = tabs.Length - 1; i >= 0; i--) { if (visiblePages[i] == owner.SelectedPage) { continue; } if (tabs[i].ShowCloseBox) { tabs[i].ShowCloseBox = false; pixelsReclaimed += Properties.Resources.Close.Width; for (int j = i + 1; j < tabs.Length; j++) { tabs[j].Location.X -= Properties.Resources.Close.Width; } } if (pixelsReclaimed >= pixelsToReclaim) { break; } } // shorten text now since removing closeboxes wasn't enough if (pixelsReclaimed < pixelsToReclaim) { int shorten = (int)Math.Ceiling(pixelsToReclaim / (double)divideCount); for (int i = 0; i < tabs.Length; i++) { if (visiblePages[i] == owner.SelectedPage) { continue; } tabs[i].textSize.Width -= shorten; for (int j = i + 1; j < tabs.Length; j++) { tabs[j].Location.X -= shorten; } } } } }
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); UpdateTabLocations(); Brush selBrush = new SolidBrush(owner.Navigator.PageBackColor); Pen pathPen = SystemPens.ControlDark; Rectangle pageExtendRect = new Rectangle(); switch (owner.Navigator.Location) { case NavigatorLocation.Bottom: pageExtendRect = new Rectangle(0, 0, ClientSize.Width, pageHeight); break; case NavigatorLocation.Top: pageExtendRect = new Rectangle(0, NavMinSize.Height - pageHeight, ClientSize.Width, pageHeight); break; } e.Graphics.FillRectangle(selBrush, pageExtendRect); // draw the tab outline GraphicsPath path = new GraphicsPath(); Point drawPoint = new Point(0, pageHeight); for (int i = 0; i < visiblePages.Count; i++) { TabRenderInfo info = tabs[i]; Rectangle rect = tabs[i].Bounds; NotebookPage page = visiblePages[i]; Font thisFont = this.Font; drawPoint = rect.Location; switch (owner.Navigator.Location) { case NavigatorLocation.Top: drawPoint.Y += tabMargin; break; } // fill background of the selected page if (owner.SelectedPage == page) { Rectangle fillRect = new Rectangle(); thisFont = mBoldFont; // add the right lines to the path to go around the tab switch (owner.Navigator.Location) { case NavigatorLocation.Top: path.AddLines(new Point[] { new Point(rect.Left, rect.Bottom), new Point(rect.Left, rect.Top + 2), new Point(rect.Left + 2, rect.Top), new Point(rect.Right - 2, rect.Top), new Point(rect.Right, rect.Top + 2), new Point(rect.Right, rect.Bottom) }); fillRect = new Rectangle( rect.Left + 1, rect.Top + 1, rect.Width - 1, rect.Height); break; case NavigatorLocation.Bottom: path.AddLines(new Point[] { rect.Location, new Point(rect.Left, rect.Bottom - 2), new Point(rect.Left + 2, rect.Bottom), new Point(rect.Right - 2, rect.Bottom), new Point(rect.Right, rect.Bottom - 2), new Point(rect.Right, rect.Top) }); fillRect = new Rectangle( rect.Left + 1, rect.Top, rect.Width - 1, rect.Height - 1); break; } e.Graphics.FillRectangle(selBrush, fillRect); } else { switch (owner.Navigator.Location) { case NavigatorLocation.Bottom: path.AddLine(rect.Location, new Point(rect.Right, rect.Top)); break; case NavigatorLocation.Top: path.AddLine(new Point(rect.X, rect.Bottom), new Point(rect.Right, rect.Bottom)); break; } if (i > 0) { e.Graphics.DrawLine(pathPen, new Point(rect.Left, rect.Top + 4), new Point(rect.Left, rect.Bottom - 4)); } } drawPoint.X += tabMargin; // draw page image if (page.Image != null) { drawPoint.X += imageMargin; Rectangle imageRect = new Rectangle(drawPoint, info.imageSize); imageRect.Y += (rect.Height - imageRect.Height) / 2; e.Graphics.DrawImage(page.Image, imageRect); drawPoint.X += info.imageSize.Width + imageMargin; } if (navProperties.AllowClose && info.ShowCloseBox) { Image image = Properties.Resources.Close; if (mOverCloseBox == i) { image = Properties.Resources.CloseMouseOver; } e.Graphics.DrawImage(image, info.CloseBox); } Rectangle textRect = Rectangle.FromLTRB( drawPoint.X, drawPoint.Y, rect.Right - tabMargin, rect.Bottom - tabMargin - 1); TextRenderer.DrawText(e.Graphics, page.Text, thisFont, textRect, ForeColor, TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine | TextFormatFlags.NoPrefix); } if (path.PointCount > 0) { switch (owner.Navigator.Location) { case NavigatorLocation.Bottom: path.AddLine(Point.Round(path.GetLastPoint()), new Point(ClientRectangle.Right, drawPoint.Y)); break; case NavigatorLocation.Top: path.AddLine(Point.Round(path.GetLastPoint()), new Point(ClientRectangle.Right, TabHeight)); break; } e.Graphics.DrawPath(pathPen, path); } }