/// <summary> /// Renders the pager text using the results of SetupPagerText. /// </summary> protected virtual void RenderPagerText(Cairo.Context context, Pango.Layout layout, Gdk.Rectangle bounds) { int w, h; layout.GetPixelSize(out w, out h); context.MoveTo(bounds.X + (bounds.Width - w) / 2, bounds.Y + (bounds.Height - h) / 2); context.Color = PagerTextColor; PangoCairoHelper.ShowLayout(context, layout); layout.Dispose(); }
//FIXME: respect damage regions not just the whole areas, and skip more work when possible protected override bool OnExposeEvent(Gdk.EventExpose evnt) { if (sections.Count == 0) { return(false); } var alloc = Allocation; int bw = (int)BorderWidth; double halfLineWidth = borderLineWidth / 2.0; int bw2 = bw * 2; int w = alloc.Width - bw2; int h = alloc.Height - bw2; using (var cr = CairoHelper.Create(evnt.Window)) { CairoHelper.Region(cr, evnt.Region); cr.Clip(); cr.Translate(alloc.X + bw, alloc.Y + bw); var borderCol = Convert(Style.Dark(StateType.Normal)); cr.SetSourceColor(borderCol); cr.Rectangle(halfLineWidth, halfLineWidth, w - borderLineWidth, h - borderLineWidth); cr.LineWidth = borderLineWidth; cr.Stroke(); cr.Translate(borderLineWidth, borderLineWidth); w = w - (2 * borderLineWidth); using (LinearGradient unselectedGrad = new LinearGradient(0, 0, 0, headerHeight), hoverGrad = new LinearGradient(0, 0, 0, headerHeight), selectedGrad = new LinearGradient(0, 0, 0, headerHeight) ) { var unselectedCol = Convert(Style.Mid(StateType.Normal)); var unselectedTextCol = Convert(Style.Text(StateType.Normal)); unselectedCol.A = 0.6; unselectedGrad.AddColorStop(0, unselectedCol); unselectedCol.A = 1; unselectedGrad.AddColorStop(1, unselectedCol); var hoverCol = Convert(Style.Mid(StateType.Prelight)); var hoverTextCol = Convert(Style.Text(StateType.Prelight)); hoverCol.A = 0.6; hoverGrad.AddColorStop(0, unselectedCol); hoverCol.A = 1; hoverGrad.AddColorStop(1, unselectedCol); var selectedCol = Convert(Style.Mid(StateType.Normal)); var selectedTextCol = Convert(Style.Text(StateType.Normal)); selectedCol.A = 0.6; selectedGrad.AddColorStop(0, selectedCol); selectedCol.A = 1; selectedGrad.AddColorStop(1, selectedCol); for (int i = 0; i < sections.Count; i++) { var section = sections[i]; bool isActive = activeIndex == i; bool isHover = hoverIndex == i; cr.Rectangle(0, 0, w, headerHeight); cr.SetSource(isActive? selectedGrad : (isHover? hoverGrad : unselectedGrad)); cr.Fill(); cr.SetSourceColor(isActive? selectedTextCol : (isHover? hoverTextCol : unselectedTextCol)); layout.SetText(section.Title); layout.Ellipsize = Pango.EllipsizeMode.End; layout.Width = (int)((w - headerPadding - headerPadding) * Pango.Scale.PangoScale); cr.MoveTo(headerPadding, headerPadding); PangoCairoHelper.ShowLayout(cr, layout); cr.MoveTo(-halfLineWidth, i > activeIndex? -halfLineWidth : headerHeight + halfLineWidth); cr.RelLineTo(w + borderLineWidth, 0.0); cr.SetSourceColor(borderCol); cr.Stroke(); cr.Translate(0, headerHeight + borderLineWidth); if (isActive) { cr.Translate(0, section.Child.Allocation.Height + borderLineWidth); } } } } PropagateExpose(sections[activeIndex].Child, evnt); return(true); // base.OnExposeEvent (evnt); }
protected override bool OnExposeEvent(EventExpose evnt) { using (var ctx = Gdk.CairoHelper.Create(GdkWindow)) { ctx.Rectangle(0, 0, Allocation.Width, Allocation.Height); using (var g = new Cairo.LinearGradient(0, 0, 0, Allocation.Height)) { g.AddColorStop(0, Styles.BreadcrumbBackgroundColor); g.AddColorStop(1, Styles.BreadcrumbGradientEndColor); ctx.SetSource(g); } ctx.Fill(); if (widths == null) { return(true); } // Calculate the total required with, and the reduction to be applied in case it doesn't fit the available space int totalWidth = widths.Sum(); totalWidth += leftPadding + (arrowSize + arrowRightPadding) * leftPath.Length - 1; totalWidth += rightPadding + arrowSize * rightPath.Length - 1; int[] currentWidths = widths; bool widthReduced = false; int overflow = totalWidth - Allocation.Width; if (overflow > 0) { currentWidths = ReduceWidths(overflow); widthReduced = true; } // Render the paths int textTopPadding = topPadding + (height - textHeight) / 2; int xpos = leftPadding, ypos = topPadding; for (int i = 0; i < leftPath.Length; i++) { bool last = i == leftPath.Length - 1; // Reduce the item size when required int itemWidth = currentWidths [i]; int x = xpos; xpos += itemWidth; if (hoverIndex >= 0 && hoverIndex < Path.Length && leftPath [i] == Path [hoverIndex] && (menuVisible || pressed || hovering)) { DrawButtonBorder(ctx, x - padding, itemWidth + padding + padding); } int textOffset = 0; if (leftPath [i].DarkIcon != null) { int iy = (height - leftPath [i].DarkIcon.Height) / 2 + topPadding; Gdk.CairoHelper.SetSourcePixbuf(ctx, leftPath [i].DarkIcon, x, iy); ctx.Paint(); textOffset += leftPath [i].DarkIcon.Width + iconSpacing; } layout.Attributes = (i == activeIndex) ? boldAtts : null; layout.SetMarkup(leftPath [i].Markup); ctx.Save(); // If size is being reduced, ellipsize it bool showText = true; if (widthReduced) { int w = itemWidth - textOffset; if (w > 0) { ctx.Rectangle(x + textOffset, textTopPadding, w, height); ctx.Clip(); } else { showText = false; } } else { layout.Width = -1; } if (showText) { // Text ctx.SetSourceColor(Styles.BreadcrumbTextColor.ToCairoColor()); ctx.MoveTo(x + textOffset, textTopPadding); PangoCairoHelper.ShowLayout(ctx, layout); } ctx.Restore(); if (!last) { xpos += arrowLeftPadding; if (leftPath [i].IsPathEnd) { Style.PaintVline(Style, GdkWindow, State, evnt.Area, this, "", ypos, ypos + height, xpos - arrowSize / 2); } else { int arrowH = Math.Min(height, arrowSize); int arrowY = ypos + (height - arrowH) / 2; DrawPathSeparator(ctx, xpos, arrowY, arrowH); } xpos += arrowSize + arrowRightPadding; } } int xposRight = Allocation.Width - rightPadding; for (int i = 0; i < rightPath.Length; i++) { // bool last = i == rightPath.Length - 1; // Reduce the item size when required int itemWidth = currentWidths [i + leftPath.Length]; xposRight -= itemWidth; xposRight -= arrowSize; int x = xposRight; if (hoverIndex >= 0 && hoverIndex < Path.Length && rightPath [i] == Path [hoverIndex] && (menuVisible || pressed || hovering)) { DrawButtonBorder(ctx, x - padding, itemWidth + padding + padding); } int textOffset = 0; if (rightPath [i].DarkIcon != null) { Gdk.CairoHelper.SetSourcePixbuf(ctx, rightPath [i].DarkIcon, x, ypos); ctx.Paint(); textOffset += rightPath [i].DarkIcon.Width + padding; } layout.Attributes = (i == activeIndex) ? boldAtts : null; layout.SetMarkup(rightPath [i].Markup); ctx.Save(); // If size is being reduced, ellipsize it bool showText = true; if (widthReduced) { int w = itemWidth - textOffset; if (w > 0) { ctx.Rectangle(x + textOffset, textTopPadding, w, height); ctx.Clip(); } else { showText = false; } } else { layout.Width = -1; } if (showText) { // Text ctx.SetSourceColor(Styles.BreadcrumbTextColor.ToCairoColor()); ctx.MoveTo(x + textOffset, textTopPadding); PangoCairoHelper.ShowLayout(ctx, layout); } ctx.Restore(); } ctx.MoveTo(0, Allocation.Height - 0.5); ctx.RelLineTo(Allocation.Width, 0); ctx.SetSourceColor(Styles.BreadcrumbBottomBorderColor); ctx.LineWidth = 1; ctx.Stroke(); } return(true); }