diff --git a/_stylesheet.scss b/_stylesheet.scss index c39c72fd0..7f1417bbf 100644 --- a/_stylesheet.scss +++ b/_stylesheet.scss @@ -354,14 +354,55 @@ $dock_style_modes: [null, shrink, extended, extended-shrink]; } #dashtodockContainer.dashtodock .progress-bar { - /* Customization of the progress bar style, e.g.: - // track colors (the "background") - -progress-bar-track-filling: rgba(0.25, 0.25, 0.25, 0,75); - -progress-bar-track-border: rgba(0.75, 0.75, 0.75, 0,25); - // progress bar colors - -progress-bar-background: rgba(0.8, 0.8, 0.8, 1); - -progress-bar-border: rgba(0.9, 0.9, 0.9, 1); - */ + /* Customization of the progress bar style. The possible elements + * are: + * + * -XXXXXX-YYYYYY: plain color + * -XXXXXX-YYYYYY-color-start: start color for gradient + * -XXXXXX-YYYYYY-color-end: end color for gradient + * -XXXXXX-YYYYYY-offset-start: offset for start color in gradient (0-1) + * -XXXXXX-YYYYYY-offset-end: offset for end color in gradient (0-1) + * -XXXXXX-line-width: width value for the line used for the border + * + * XXXXXX can be either + * + * progress-bar-track: the "track" over which the progress bar is shown + * progress-bar: the progress bar itself + * + * YYYYYY can be either + * + * background: for the background color + * border: for the border color + * + * plain color entries have priority over gradients, so if both are set for + * an element, the plain color will be used. + * + * Examples: + * + * -progress-bar-track-background: rgba(128, 128, 0, 0.75); + * -progress-bar-track-border: rgba(0, 0, 255, 0.25); + * + * -progress-bar-background: rgba(0, 204, 204, 1); + * -progress-bar-border: rgba(230, 230, 230, 1); + * + * Default values when these entries aren't set are equivalent to: + * -progress-bar-track-background-color-start: 64, 64, 64, 1.0 + * -progress-bar-track-background-color-end: 89, 89, 89, 1.0 + * -progress-bar-track-background-start-offset: 0.4 + * -progress-bar-track-background-end-offset: 0.9 + * -progress-bar-track-border-color-start: 128, 128, 128, 0.1 + * -progress-bar-track-border-color-end: 89, 89, 89, 0.4 + * -progress-bar-track-border-start-offset: 0.5 + * -progress-bar-track-border-end-offset: 0.9 + * -progress-bar-track-line-width: 1 + * -progress-bar-background: 204, 204, 204, 1.0 + * -progress-bar-border: 230, 230, 230, 1.0 + * -progress-bar-line-width: 1 + */ + -progress-bar-track-background: rgba(0, 0, 0, 0.45); + -progress-bar-track-border: rgba(0, 0, 0, 0.7); + -progress-bar-background: rgba(255, 255, 255, 1.0); + -progress-bar-border: rgba(255, 255, 255, 1.0); } #dashtodockContainer.top #dash .placeholder, diff --git a/appIconIndicators.js b/appIconIndicators.js index 174dcb292..e38510d19 100644 --- a/appIconIndicators.js +++ b/appIconIndicators.js @@ -677,6 +677,34 @@ class RunningIndicatorBinary extends RunningIndicatorDots { * Unity like notification and progress indicators */ class UnityIndicator extends IndicatorBase { + static defaultProgressBar = { + // default values for the progress bar itself + background: { + colorStart: {red: 204, green: 204, blue: 204, alpha: 255}, + colorEnd: null, + }, + border: { + colorStart: {red: 230, green: 230, blue: 230, alpha: 255}, + colorEnd: null, + }, + }; + + static defaultProgressBarTrack = { + // default values for the progress bar track + background: { + colorStart: {red: 64, green: 64, blue: 64, alpha: 255}, + colorEnd: {red: 89, green: 89, blue: 89, alpha: 255}, + offsetStart: 0.4, + offsetEnd: 0.9, + }, + border: { + colorStart: {red: 128, green: 128, blue: 128, alpha: 26}, + colorEnd: {red: 204, green: 204, blue: 204, alpha: 102}, + offsetStart: 0.5, + offsetEnd: 0.9, + }, + }; + constructor(source) { super(source); @@ -840,6 +868,72 @@ class UnityIndicator extends IndicatorBase { this._progressOverlayArea?.queue_repaint(); } + _readGradientData(node, elementName, defaultValues) { + const output = { + colorStart: defaultValues.colorStart, + colorEnd: defaultValues.colorEnd, + offsetStart: defaultValues.offsetStart ?? 0.0, + offsetEnd: defaultValues.offsetEnd ?? 1.0, + }; + + const [hasElementName, elementNameValue] = node.lookup_color(elementName, false); + if (hasElementName) { + output.colorStart = elementNameValue; + output.colorEnd = null; + } else { + const [hasColorStart, colorStartValue] = node.lookup_color(`${elementName}-color-start`, false); + const [hasColorEnd, colorEndValue] = node.lookup_color(`${elementName}-color-end`, false); + if (hasColorStart && hasColorEnd) { + output.colorStart = colorStartValue; + output.colorEnd = colorEndValue; + } + } + + const [hasOffsetStart, offsetStartvalue] = node.lookup_color(`${elementName}-offset-start`, false); + if (hasOffsetStart) + output.offsetStart = offsetStartvalue; + + const [hasOffsetEnd, offsetEndValue] = node.lookup_color(`${elementName}-offset-end`, false); + if (hasOffsetEnd) + output.offsetEnd = offsetEndValue; + + return output; + } + + _readElementData(node, elementName, defaultValues) { + const defaultLineWidth = defaultValues.lineWidth ?? 1.0; + const [hasValue, lineWidth] = node.lookup_double(`${elementName}-line-width`, false); + + return { + background: this._readGradientData(node, `${elementName}-background`, defaultValues.background), + border: this._readGradientData(node, `${elementName}-border`, defaultValues.border), + lineWidth: hasValue ? lineWidth : defaultLineWidth, + }; + } + + _createGradient(values, x0, y0, x1, y1) { + if (values.colorEnd) { + const gradient = new Cairo.LinearGradient(x0, y0, x1, y1); + gradient.addColorStopRGBA(values.offsetStart, + values.colorStart.red / 255, + values.colorStart.green / 255, + values.colorStart.blue / 255, + values.colorStart.alpha / 255); + gradient.addColorStopRGBA(values.offsetEnd, + values.colorEnd.red / 255, + values.colorEnd.green / 255, + values.colorEnd.blue / 255, + values.colorEnd.alpha / 255); + return gradient; + } else { + const gradient = Cairo.SolidPattern.createRGBA(values.colorStart.red / 255, + values.colorStart.green / 255, + values.colorStart.blue / 255, + values.colorStart.alpha / 255); + return gradient; + } + } + _drawProgressOverlay(area) { const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); const [surfaceWidth, surfaceHeight] = area.get_surface_size(); @@ -850,58 +944,49 @@ class UnityIndicator extends IndicatorBase { let x = Math.floor((surfaceWidth - iconSize) / 2); let y = Math.floor((surfaceHeight - iconSize) / 2); - const lineWidth = Math.floor(Number(scaleFactor)); + const baseLineWidth = Math.floor(Number(scaleFactor)); const padding = Math.floor(iconSize * 0.05); let width = iconSize - 2.0 * padding; let height = Math.floor(Math.min(18.0 * scaleFactor, 0.20 * iconSize)); x += padding; y += iconSize - height - padding; + const node = this._progressOverlayArea.get_theme_node(); + + const progressBarTrack = this._readElementData(node, + '-progress-bar-track', + UnityIndicator.defaultProgressBarTrack); + + const progressBar = this._readElementData(node, + '-progress-bar', + UnityIndicator.defaultProgressBar); + + // Draw the track + let lineWidth = baseLineWidth * progressBarTrack.lineWidth; cr.setLineWidth(lineWidth); - // Draw the background x += lineWidth; y += lineWidth; width -= 2.0 * lineWidth; height -= 2.0 * lineWidth; - let hasColor, bg, bd, fg; - const node = this._progressOverlayArea.get_theme_node(); - - [hasColor, bg] = node.lookup_color('-progress-bar-track-filling', false); - if (!hasColor) - bg = new Clutter.Color({red: 64, green: 64, blue: 64, alpha: 192}); - - [hasColor, fg] = node.lookup_color('-progress-bar-track-border', false); - if (!hasColor) - fg = new Clutter.Color({red: 192, green: 192, blue: 192, alpha: 64}); - - let fill = Cairo.SolidPattern.createRGBA(bg.red / 255, bg.green / 255, bg.blue / 255, bg.alpha / 255); - let stroke = Cairo.SolidPattern.createRGBA( - fg.red / 255, fg.green / 255, fg.blue / 255, fg.alpha / 255); + let fill = this._createGradient(progressBarTrack.background, 0, y, 0, y + height); + let stroke = this._createGradient(progressBarTrack.border, 0, y, 0, y + height); Utils.drawRoundedLine(cr, x + lineWidth / 2.0, y + lineWidth / 2.0, width, height, true, true, stroke, fill); // Draw the finished bar + lineWidth = baseLineWidth * progressBar.lineWidth; + cr.setLineWidth(lineWidth); + x += lineWidth; y += lineWidth; width -= 2.0 * lineWidth; height -= 2.0 * lineWidth; const finishedWidth = Math.ceil(this._progress * width); - - [hasColor, bg] = node.lookup_color('-progress-bar-background', false); - if (!hasColor) - bg = new Clutter.Color({red: 204, green: 204, blue: 204, alpha: 255}); - - [hasColor, bd] = node.lookup_color('-progress-bar-border', false); - if (!hasColor) - bd = new Clutter.Color({red: 230, green: 230, blue: 230, alpha: 255}); - - stroke = Cairo.SolidPattern.createRGBA( - bd.red / 255, bd.green / 255, bd.blue / 255, bd.alpha / 255); - fill = Cairo.SolidPattern.createRGBA( - bg.red / 255, bg.green / 255, bg.blue / 255, bg.alpha / 255); + fill = this._createGradient(progressBar.background, 0, y, 0, y + height); + stroke = this._createGradient(progressBar.border, 0, y, 0, y + height); if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) { Utils.drawRoundedLine(cr,