void DrawErrorAnimation(Cairo.Context context, StatusArea.RenderArg arg) { const int surfaceWidth = 2000; double opacity; int progress; if (arg.ErrorAnimationProgress < .5f) { progress = (int)(arg.ErrorAnimationProgress * arg.Allocation.Width * 2.4); opacity = 1.0d; } else { progress = (int)(arg.ErrorAnimationProgress * arg.Allocation.Width * 2.4); opacity = 1.0d - (arg.ErrorAnimationProgress - .5d) * 2; } LayoutRoundedRectangle(context, arg.Allocation); context.Clip(); context.CachedDraw(surface: ref errorSurface, position: new Gdk.Point(arg.Allocation.X - surfaceWidth + progress, arg.Allocation.Y), size: new Gdk.Size(surfaceWidth, arg.Allocation.Height), opacity: (float)opacity, draw: (c, o) => { // The smaller the pixel range of our gradient the less error there will be in it. using (var lg = new LinearGradient(surfaceWidth - 250, 0, surfaceWidth, 0)) { lg.AddColorStop(0.00, Styles.WithAlpha(Styles.StatusBarErrorColor, 0.15 * o)); lg.AddColorStop(0.10, Styles.WithAlpha(Styles.StatusBarErrorColor, 0.15 * o)); lg.AddColorStop(0.88, Styles.WithAlpha(Styles.StatusBarErrorColor, 0.30 * o)); lg.AddColorStop(1.00, Styles.WithAlpha(Styles.StatusBarErrorColor, 0.00 * o)); c.SetSource(lg); c.Paint(); } }); context.ResetClip(); }
public void Render(Cairo.Context context, StatusArea.RenderArg arg, Gtk.Widget widget) { context.CachedDraw(surface: ref backgroundSurface, region: arg.Allocation, draw: (c, o) => DrawBackground(c, new Gdk.Rectangle(0, 0, arg.Allocation.Width, arg.Allocation.Height))); if (arg.BuildAnimationOpacity > 0.001f) { DrawBuildEffect(context, arg.Allocation, arg.BuildAnimationProgress, arg.BuildAnimationOpacity); } if (arg.ErrorAnimationProgress > 0.001 && arg.ErrorAnimationProgress < .999) { DrawErrorAnimation(context, arg); } DrawBorder(context, arg.Allocation); if (arg.HoverProgress > 0.001f) { context.Clip(); int x1 = arg.Allocation.X + arg.MousePosition.X - 200; int x2 = x1 + 400; using (Cairo.LinearGradient gradient = new LinearGradient(x1, 0, x2, 0)) { Cairo.Color targetColor = Styles.StatusBarFill1Color; Cairo.Color transparentColor = targetColor; targetColor.A = .7; transparentColor.A = 0; targetColor.A = .7 * arg.HoverProgress; gradient.AddColorStop(0.0, transparentColor); gradient.AddColorStop(0.5, targetColor); gradient.AddColorStop(1.0, transparentColor); context.SetSource(gradient); context.Rectangle(x1, arg.Allocation.Y, x2 - x1, arg.Allocation.Height); context.Fill(); } context.ResetClip(); } else { context.NewPath(); } int progress_bar_x = arg.ChildAllocation.X; int progress_bar_width = arg.ChildAllocation.Width; if (arg.CurrentPixbuf != null) { int y = arg.Allocation.Y + (arg.Allocation.Height - (int)arg.CurrentPixbuf.Size.Height) / 2; context.DrawImage(widget, arg.CurrentPixbuf, arg.ChildAllocation.X, y); progress_bar_x += (int)arg.CurrentPixbuf.Width + Styles.ProgressBarOuterPadding; progress_bar_width -= (int)arg.CurrentPixbuf.Width + Styles.ProgressBarOuterPadding; } int center = arg.Allocation.Y + arg.Allocation.Height / 2; Gdk.Rectangle progressArea = new Gdk.Rectangle(progress_bar_x, center - Styles.ProgressBarHeight / 2, progress_bar_width, Styles.ProgressBarHeight); if (arg.ShowProgressBar || arg.ProgressBarAlpha > 0) { DrawProgressBar(context, arg.ProgressBarFraction, progressArea, arg); ClipProgressBar(context, progressArea); } int text_x = progress_bar_x + Styles.ProgressBarInnerPadding; int text_width = progress_bar_width - (Styles.ProgressBarInnerPadding * 2); double textTweenValue = arg.TextAnimationProgress; if (arg.LastText != null) { double opacity = Math.Max(0.0f, 1.0f - textTweenValue); DrawString(arg.LastText, arg.LastTextIsMarkup, context, text_x, center - (int)(textTweenValue * arg.Allocation.Height * 0.3), text_width, opacity, arg.Pango, arg); } if (arg.CurrentText != null) { DrawString(arg.CurrentText, arg.CurrentTextIsMarkup, context, text_x, center + (int)((1.0f - textTweenValue) * arg.Allocation.Height * 0.3), text_width, Math.Min(textTweenValue, 1.0), arg.Pango, arg); } if (arg.ShowProgressBar || arg.ProgressBarAlpha > 0) { context.ResetClip(); } }
void DrawString(string text, bool isMarkup, Cairo.Context context, int x, int y, int width, double opacity, Pango.Context pango, StatusArea.RenderArg arg) { Pango.Layout pl = new Pango.Layout(pango); if (isMarkup) { pl.SetMarkup(text); } else { pl.SetText(text); } pl.FontDescription = Styles.StatusFont; pl.FontDescription.AbsoluteSize = Pango.Units.FromPixels(Styles.StatusFontPixelHeight); pl.Ellipsize = Pango.EllipsizeMode.End; pl.Width = Pango.Units.FromPixels(width); int w, h; pl.GetPixelSize(out w, out h); context.Save(); // use widget height instead of message box height as message box does not have a true height when no widgets are packed in it // also ensures animations work properly instead of getting clipped context.Rectangle(new Rectangle(x, arg.Allocation.Y, width, arg.Allocation.Height)); context.Clip(); // Subtract off remainder instead of drop to prefer higher centering when centering an odd number of pixels context.MoveTo(x, y - h / 2 - (h % 2)); context.SetSourceColor(Styles.WithAlpha(FontColor(), opacity)); Pango.CairoHelper.ShowLayout(context, pl); IsEllipsized = pl.IsEllipsized; pl.Dispose(); context.Restore(); }
void DrawProgressBar(Cairo.Context context, double progress, Gdk.Rectangle bounding, StatusArea.RenderArg arg) { LayoutRoundedRectangle(context, new Gdk.Rectangle(bounding.X, bounding.Y, (int)(bounding.Width * progress), bounding.Height), 0, 0, 1); context.Clip(); LayoutRoundedRectangle(context, bounding, 0, 0, 1); context.SetSourceColor(Styles.WithAlpha(Styles.StatusBarProgressBackgroundColor, Styles.StatusBarProgressBackgroundColor.A * arg.ProgressBarAlpha)); context.FillPreserve(); context.ResetClip(); context.SetSourceColor(Styles.WithAlpha(Styles.StatusBarProgressOutlineColor, Styles.StatusBarProgressOutlineColor.A * arg.ProgressBarAlpha)); context.LineWidth = 1; context.Stroke(); }