diff --git a/src/_functions.scss b/src/_functions.scss index 7adce8e..0cef06f 100644 --- a/src/_functions.scss +++ b/src/_functions.scss @@ -1,260 +1,260 @@ @charset "UTF-8"; // // Theme color functions // // Button Color @function b_color($c: normal) { @if $c == normal { @return $ButtonBackgroundNormal; } @if $c == hover { @return $ButtonDecorationHover; } @if $c == active { @return $ButtonDecorationFocus; } @if $c == text { @return $ButtonForegroundNormal; } @if $c == active-text { @return $SelectionForegroundNormal; } } // Selection Color @function s_color($c: normal) { @if $c == normal { @return $SelectionBackgroundNormal; } @if $c == hover { @return $SelectionDecorationHover; } @if $c == text { @return $SelectionForegroundNormal; } @if $c == backdrop { @return transparentize($SelectionBackgroundNormal,0.5); } } // View Color @function v_color($c: normal) { @if $c == normal { @return $ViewBackgroundNormal; } @if $c == hover { @return $ViewDecorationHover; } @if $c == active { @return $ViewDecorationFocus; } @if $c == text { @return $ViewForegroundNormal; } } // Window Color @function w_color($c: normal) { @if $c == normal { @return $WindowBackgroundNormal; } @if $c == text { @return $WindowForegroundNormal; } } // Titlebar color @function t_color($c: text) { @if $c == text { - @return $WindowForegroundNormal; + @return $WMactiveForeground; } @if $c == background { - @return $WindowBackgroundNormal; + @return $WMactiveBackground; } @if $c == background-light { @return $WindowBackgroundNormal; } @if $c == backdrop-text { @return $WMinactiveForeground; } @if $c == backdrop-background { - @return $WindowBackgroundNormal; + @return $WMinactiveBackground; } } @function tooltip($c: text) { @if $c == text { @return $TooltipForegroundNormal; } @if $c == background { @return $TooltipBackgroundNormal; } @if $c == border { @return mix($TooltipForegroundNormal, $TooltipBackgroundNormal, 25%); } } @function button_gradient($c, $state: normal) { @if $state == normal { @return linear-gradient(to bottom, change-color($c, $lightness: min(lightness($c)*1.01,100%)), change-color($c, $lightness:min(lightness($c)/1.03,100%))); } @else { @return linear-gradient(to bottom, change-color($c, $lightness: min(lightness($c)*1.03,100%)), change-color($c, $lightness:min(lightness($c)/1.10,100%))); } } $border_color: mix($WindowBackgroundNormal,$WindowForegroundNormal, 75%); $menu_color: w_color(normal); $link_color: $ViewForegroundLink; $link_visited_color: $ViewForegroundVisited; $warning_color: $ViewForegroundNeutral; $error_color: $ViewForegroundNegative; $success_color: $ViewForegroundPositive; $destructive_color: $error_color; $trough_color: mix(w_color(normal),w_color(text),70%); $scrollbar_color: mix($trough_color,v_color(text),50%); // // Color effects // // // Color maps for color effect functions // $Color: ( Disabled: $DisabledColor, Inactive: $InactiveColor ); $ColorAmount: ( Disabled: $DisabledColorAmount, Inactive: $InactiveColorAmount ); $ColorEffect: ( Disabled: $DisabledColorEffect, Inactive: $InactiveColorEffect ); $ContrastAmount: ( Disabled: $DisabledContrastAmount, Inactive: $InactiveContrastAmount ); $ContrastEffect: ( Disabled: $DisabledContrastEffect, Inactive: $InactiveContrastEffect ); $IntensityAmount: ( Disabled: $DisabledIntensityAmount, Inactive: $InactiveIntensityAmount ); $IntensityEffect: ( Disabled: $DisabledIntensityEffect, Inactive: $InactiveIntensityEffect ); $r: 3px; // standard radius @function insensitive($c) { @return Color(Intensity(Contrast($c, Disabled), Disabled), Disabled); } @function backdrop($c) { @if $InactiveEnable == true { @return Color(Intensity(Contrast($c, Inactive), Inactive), Inactive); } @else { @return $c; } } @function Contrast($c, $state) { @if map-get($ContrastEffect, $state) == 0 { @return $c; } @if map-get($ContrastEffect, $state) == 1 { @if lightness(w_color()) > lightness(w_color(text)) { @if lightness($c) < lightness(w_color()) or ($c == t_color(text) and lightness(t_color(background)) <= lightness(t_color(text))) { @return transparentize($c, map-get($ContrastAmount, $state)); } @else { @return $c; } } @if lightness(w_color()) <= lightness(w_color(text)) { @if lightness($c) > lightness(w_color()) or ($c == t_color(text) and lightness(t_color(background)) > lightness(t_color(text))) { @return transparentize($c, map-get($ContrastAmount, $state)); } @else { @return $c; } } } @if map-get($ContrastEffect, $state) == 2 { @if lightness(w_color()) > lightness(w_color(text)) { // don't know what a reasonable lightness treshhold is for Contrast @if lightness($c) < lightness(w_color()) or ($c == t_color(text) and lightness(t_color(background)) <= lightness(t_color(text))) { @return transparentize($c, map-get($ContrastAmount, $state)); } @else { @return $c; } } @if lightness(w_color()) <= lightness(w_color(text)) { @if lightness($c) > lightness(w_color()) or ($c == t_color(text) and lightness(t_color(background)) > lightness(t_color(text))){ @return transparentize($c, map-get($ContrastAmount, $state)); } @else { @return $c; } } } } @function Color($c, $state) { @if map-get($ColorEffect, $state) ==0 { @return $c; } @if map-get($ColorEffect, $state) ==1 { @if map-get($ColorAmount, $state) >=0 { @return desaturate($c, percentage(map-get($ColorAmount, $state))); } @else { @return saturate($c, percentage(abs(map-get($ColorAmount, $state)))); } } @if map-get($ColorEffect, $state)==2 or map-get($ColorEffect, $state)==3 { // 2 and 3 seem to do the same @return mix(map-get($Color, $state),$c, percentage(map-get($ColorAmount, $state))); } } @function Intensity($c, $state) { @if map-get($IntensityEffect, $state) == 0 { @return $c; } @if map-get($IntensityEffect, $state) == 1 { @if map-get($IntensityAmount, $state) >= 0 { @return mix(white, $c, percentage(map-get($IntensityAmount, $state))); } @else { @return mix(black, $c, percentage(abs(map-get($IntensityAmount, $state)))); } } @if map-get($IntensityEffect, $state) == 2 { @if map-get($IntensityAmount, $state) == -1 { @return change-color($c, $lightness: 100%); } @else { @return change-color($c, $lightness: min(lightness($c)/(1+map-get($IntensityAmount, $state)),100%)); } } @if map-get($IntensityEffect, $state) == 3 { @return change-color($c, $lightness: min(lightness($c)*(1+map-get($IntensityAmount, $state)),100%)); } } @function alpha2solid($c,$background) { $amount:alpha($c); $c:rgb(red($c),green($c),blue($c)); @return mix($c,$background,$amount); } diff --git a/src/gtk320/widgets/_headerbar.scss b/src/gtk320/widgets/_headerbar.scss index 148ebbb..f2127f9 100644 --- a/src/gtk320/widgets/_headerbar.scss +++ b/src/gtk320/widgets/_headerbar.scss @@ -1,170 +1,171 @@ @charset "UTF-8"; /*************** * Header bars * ***************/ %titlebar, headerbar { transition: none; padding: 0px 6px; border-width: 0px 0px 1px 0px; border-radius: 3px 3px 0px 0px; border-style: solid; border-color: $border_color; color: t_color(text); - background-image: linear-gradient(to bottom,t_color(background-light),t_color(background)); + background-image: none; + background-color: t_color(background); &:backdrop { border-color: transparent; background-image: none; background-color: t_color(backdrop-background); color: t_color(backdrop-text); box-shadow: none; } label { font-weight: normal; &:backdrop { color: t_color(backdrop-text); } } .path-bar button { color: t_color(text); font-weight: normal; &:backdrop { color: t_color(backdrop-text)} } button { transition: none; @include button(undecorated, $tc: t_color(text)); &.flat { @include button(undecorated,$tc: t_color(text)); } &:hover { @include button(hover, $tc: t_color(text)); &:backdrop { border-color: t_color(backdrop-background); } } &:active, &:checked { @include button(active); &:hover { @include button(active-hover); } &:backdrop { background-image: none; background-color: t_color(backdrop-background); border-color: t_color(backdrop-background); color: t_color(backdrop-text); } } &.suggested-action { @extend %suggested-action; } &:backdrop { border-color: transparent; background-image: none; background-color: t_color(backdrop-background); color: t_color(backdrop-text); } &.flat:backdrop, &.flat:backdrop:disabled, &:disabled:backdrop { background-image: none; background-color: t_color(backdrop-background); color: t_color(backdrop-text); border-color: transparent; } &.flat:disabled { @extend %undecorated_button;; color: insensitive(t_color(text)); } &:disabled { background-color: transparent; background-image: none; border-color: transparent; color: insensitive(t_color(text)); &:active, &:checked { @include button(insensitive-active); } } } .title { font-weight: normal; padding: 0px 12px; &:backdrop { color: t_color(backdrop-text)} } .subtitle { font-size: smaller; padding: 0 12px; @extend .dim-label; &:backdrop { color: t_color(backdrop-text)} } separator { border-width: 0px; background-color: transparent; background-image: none; border-color: transparent; } &.selection-mode { @extend .info; &.suggested-action { @extend %suggested-action; } .subtitle:link { @extend *:link:selected; } .selection-menu { padding: 4px 6px; GtkArrow { -GtkArrow-arrow-scaling: 1; } .arrow { -gtk-icon-source: -gtk-icontheme('pan-down-symbolic'); -gtk-icon-shadow: none; } } } .tiled &, .maximized & { border-radius: 0; // squared corners when the window is max'd or tiled } } headerbar { // add vertical margins to headerbar entries, buttons and separators to avoid them spanning the whole height entry, spinbutton, separator, button { margin-top: 3px; margin-bottom: 3px; } } %suggested-action { background-image: none; background-color: b_color(active); &:hover { background-color: b_color(hover); color: b_color(text) } &:disabled { background-color: transparent; background-image: none; color: insensitive(t_color(text)); &:active, &:checked { @include button(insensitive-active); } } &:backdrop { background-color: t_color(backdrop-background); border-color: transparent; color: t_color(backdrop-text); &:disabled { color: insensitive(t_color(backdrop-text)); } } } diff --git a/src/render_assets.py b/src/render_assets.py index 8477d91..9c6b7ea 100755 --- a/src/render_assets.py +++ b/src/render_assets.py @@ -1,866 +1,863 @@ #!/usr/bin/env python3 import cairo import colorsys from math import pi import os import errno import sys import re import argparse def make_sure_path_exists(path): try: os.makedirs(path) except FileExistsError as exception: pass pass class ReadKdeGlobals(): def __init__(self, base_file_name): self._colors = {} self._colors = self.read_globals(base_file_name) def read_globals(self, filename): with open(filename, 'r', encoding="utf-8") as _kde: for widget in ['Disabled', 'Inactive', 'Button', 'Selection', 'Tooltip', 'View', 'Window', 'WM']: for line in _kde: if line.strip().split(':')[-1].strip('[]') == widget: break for line in _kde: if line == '\n': break key = '{0}{1}'.format(widget, line.strip().split('=')[0]) value = line.strip().split('=')[1] if value == '': continue self._colors[key] = value return self._colors class Color(object): def __init__(self, colordict, name, name2=None, amount=0): color = colordict[name] self.colordict = colordict r = float(color.split(',')[0]) g = float(color.split(',')[1]) b = float(color.split(',')[2]) if name2 is not None: color2 = colordict[name2] r = r * amount + float(color2.split(',')[0]) * (1 - amount) g = g * amount + float(color2.split(',')[1]) * (1 - amount) b = b * amount + float(color2.split(',')[2]) * (1 - amount) self.rgb255 = (int(r), int(g), int(b)) self.rgb = (r/255, g/255, b/255) self.html = '#%02x%02x%02x' % self.rgb255 self.insensitive = self._color_effect( self._intensity_effect(self.rgb, 'Disabled'), 'Disabled') self.insensitive_alpha = self._contrast_effect(self.rgb, 'Disabled') if self.colordict['InactiveEnable'] == 'false': self.inactive = self.rgb self.inactive_alpha = 1.0 else: self.inactive = self._color_effect( self._intensity_effect(self.rgb, 'Inactive'), 'Inactive') self.inactive_alpha = self._contrast_effect(self.rgb, 'Inactive') self.inactive_insensitive = self._color_effect( self._intensity_effect(self.inactive, 'Disabled'), 'Disabled') self.inactive_insensitive_alpha = max( self.inactive_alpha - (1 - self.insensitive_alpha), 0) def _mix(self, color, mix_color, amount): r = color[0] * amount + mix_color[0] * (1 - amount) g = color[1] * amount + mix_color[1] * (1 - amount) b = color[2] * amount + mix_color[2] * (1 - amount) return (r, g, b) def _lighter(self, color, amount): h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2]) v = min((1+amount)*v, 1) r, g, b = colorsys.hsv_to_rgb(h, s, v) return (r, g, b) def _darker(self, color, amount): h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2]) if amount == -1: v = 1 else: v = min(v/(1+amount), 1) r, g, b = colorsys.hsv_to_rgb(h, s, v) return (r, g, b) def _desaturate(self, color, amount): h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2]) s = min(s * (1 - amount), 1) r, g, b = colorsys.hsv_to_rgb(h, s, v) return (r, g, b) def _intensity_effect(self, color, state): effect = int(self.colordict[state + 'IntensityEffect']) amount = float(self.colordict[state + 'IntensityAmount']) if effect == 0: (r, g, b) = color elif effect == 1: if amount >= 0: (r, g, b) = self._mix((1.0, 1.0, 1.0), color, amount) else: (r, g, b) = self._mix((0.0, 0.0, 0.0), color, amount) elif effect == 2: (r, g, b) = self._darker(color, amount) elif effect == 3: (r, g, b) = self._lighter(color, amount) return (r, g, b) def _color_effect(self, color, state): effect = int(self.colordict[state + 'ColorEffect']) amount = float(self.colordict[state + 'ColorAmount']) effect_color = self.colordict[state + 'Color'] effect_color = (float(effect_color.split(',')[0])/255, float(effect_color.split(',')[1])/255, float(effect_color.split(',')[2])/255) if effect == 0: (r, g, b) = color elif effect == 1: (r, g, b) = self._desaturate(color, amount) else: (r, g, b) = self._mix(effect_color, color, amount) return (r, g, b) def _contrast_effect(self, color, state): effect = int(self.colordict[state + 'ContrastEffect']) amount = float(self.colordict[state + 'ContrastAmount']) if effect == 0: return 1.0 else: return 1.0 - amount def lighten_color(self, amount): h, s, v = colorsys.rgb_to_hsv(self.rgb[0], self.rgb[1], self.rgb[2]) v = (1+amount)*v r, g, b = colorsys.hsv_to_rgb(h, s, v) self.rgb = (r, g, b) self.rgb255 = (int(r*255), int(g*255), int(b*255)) def gradient(self, state='', alpha=1.0): if state == 'active': stop1 = self._lighter(self.rgb, 0.03) stop2 = self._darker(self.rgb, 0.10) linear = cairo.LinearGradient(1, 1, 1, 19) linear.add_color_stop_rgba( 0.0, stop1[0], stop1[1], stop1[2], alpha) linear.add_color_stop_rgba( 1.0, stop2[0], stop2[1], stop2[2], alpha) else: stop1 = self._lighter(self.rgb, 0.01) stop2 = self._darker(self.rgb, 0.03) linear = cairo.LinearGradient(1, 1, 1, 19) linear.add_color_stop_rgba( 0.0, stop1[0], stop1[1], stop1[2], alpha) linear.add_color_stop_rgba( 1.0, stop2[0], stop2[1], stop2[2], alpha) return linear class Assets(object): def __init__(self, width, height, scl=1, rotation=0, filename='png'): self.w = width self.h = height if filename == 'png': self.surface = cairo.ImageSurface( cairo.FORMAT_ARGB32, scl*width, scl*height) else: self.surface = cairo.SVGSurface(os.path.join( assets_path, filename), scl*width, scl*height) cr = self.cr = cairo.Context(self.surface) if rotation != 0: cr.translate(scl*width/2, scl*height/2) cr.rotate(rotation*pi/2) cr.translate(-scl*width/2, -scl*height/2) cr.scale(scl, scl) def background(self, color): self.cr.rectangle(0, 0, self.w, self.h) self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.fill() def line(self, color, x, y, width, height): self.cr.rectangle(x, y, width, height) self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.fill() def rounded_rectancle(self, color, width, height, x, y, radius, alpha=1.0, gradient=False): self.cr.new_sub_path() self.cr.arc(x + width - radius, y + radius, radius, -pi/2, 0) self.cr.arc(x + width - radius, y + height - radius, radius, 0, pi/2) self.cr.arc(x + radius, y + height - radius, radius, pi/2, pi) self.cr.arc(x + radius, y + radius, radius, pi, 3*pi/2) self.cr.close_path() if gradient: self.cr.set_source(color) elif color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) elif color == 'shadow': self.cr.set_source_rgba(0.0, 0.0, 0.0, 0.15) else: self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.fill() def rounded_triangle(self, color, width, height, x, y, radius, alpha=1.0): self.cr.new_sub_path() self.cr.move_to(x + width, y) self.cr.line_to(x + width, y + height - radius) self.cr.arc(x + width - radius, y + height - radius, radius, 0, pi/2) self.cr.line_to(x, y + height) self.cr.close_path() self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.fill() def circle(self, color, x, y, radius, alpha=1.0, gradient=False): self.cr.new_sub_path() self.cr.arc(x, y, radius, 0, 2*pi) self.cr.close_path() if gradient: self.cr.set_source(color) elif color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) elif color == 'shadow': self.cr.set_source_rgba(0.0, 0.0, 0.0, 0.15) else: self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.fill() def half_circle(self, color, x, y, radius, alpha=1.0): self.cr.new_sub_path() self.cr.arc(x, y, radius, -pi/4, 3*pi/4) self.cr.close_path() self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.fill() def arrow(self, color, alpha=1.0, shiftx=0, shifty=0): self.cr.new_sub_path() self.cr.move_to(shiftx + 1, shifty + 8) self.cr.line_to(shiftx + 6, shifty + 3) self.cr.line_to(shiftx + 11, shifty + 8) self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.set_line_width(1.0) self.cr.stroke() def arrow_small(self, color, alpha=1.0): self.cr.new_sub_path() self.cr.move_to(1, 6) self.cr.line_to(4, 3) self.cr.line_to(7, 6) self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.set_line_width(1.0) self.cr.stroke() def tab(self, color, width, height, x, y, radius, alpha=1.0): self.cr.move_to(width + x, y) self.cr.line_to(width + x, height - radius + y) self.cr.arc(width - radius + x, height - radius + y, radius, 0, pi/2) self.cr.line_to(radius + x, height + y) self.cr.arc(radius + x, height - radius + y, radius, pi/2, pi) self.cr.line_to(x, y) self.cr.close_path if color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) else: self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.fill() def spinbutton(self, color, width, height, x, y, radius, alpha=1.0): self.cr.move_to(width + x, y) self.cr.line_to(width + x, height - radius + y) self.cr.arc(width - radius + x, height - radius + y, radius, 0, pi/2) self.cr.line_to(x, height + y) self.cr.line_to(x, y) self.cr.close_path() if color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) else: self.cr.set_source_rgba(color[0], color[1], color[2], alpha) self.cr.fill() def notebook(self, color, width, height, x, y, radius): self.cr.move_to(x, y) self.cr.line_to(x + width - radius, y) self.cr.arc(x + width - radius, y + radius, radius, -pi/2, 0) self.cr.line_to(x + width, y + height-radius) self.cr.arc(x + width - radius, y + height - radius, radius, 0, pi/2) self.cr.line_to(x + radius, y + height) self.cr.arc(x + radius, y + height - radius, radius, pi/2, pi) self.cr.close_path() self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.fill() def minimize(self, color=None): self.cr.move_to(4, 7) self.cr.line_to(9, 12) self.cr.line_to(14, 7) if color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) else: self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.set_line_width(1.0) self.cr.stroke() def maximize(self, color=None): self.cr.move_to(4, 11) self.cr.line_to(9, 6) self.cr.line_to(14, 11) if color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) else: self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.set_line_width(1.0) self.cr.stroke() def maximize_maximized(self, color=None): self.cr.move_to(4.5, 9) self.cr.line_to(9, 4.5) self.cr.line_to(13.5, 9) self.cr.line_to(9, 13.5) self.cr.close_path() if color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) else: self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.set_line_width(1.0) self.cr.stroke() def close(self, color=None): self.cr.move_to(5, 5) self.cr.line_to(13, 13) self.cr.move_to(13, 5) self.cr.line_to(5, 13) if color is None: self.cr.set_operator(cairo.OPERATOR_CLEAR) else: self.cr.set_source_rgb(color[0], color[1], color[2]) self.cr.set_line_width(1.0) self.cr.stroke() def save(self, filename): self.surface.write_to_png(os.path.join(assets_path, filename)) def check_items(color1, color2, state, alpha=1.0): for scl in [1, 2]: if scl == 2: ending = '@2.png' else: ending = '.png' # checkboxes box = Assets(20, 20, scl) box.rounded_rectancle('shadow', 18, 18, 2, 2, 3) box.rounded_rectancle(color2, 18, 18, 1, 1, 3) box.rounded_rectancle(color1, 18, 18, 1, 1, 3, alpha=alpha) box.rounded_rectancle(color2, 16, 16, 2, 2, 2) box.save('check-unchecked' + state + ending) if state != '': box.rounded_rectancle(color1, 12, 12, 4, 4, 1, alpha=alpha) box.save('check-checked' + state + ending) box.rounded_triangle(color2, 8, 8, 6, 6, 1, alpha=alpha) box.save('check-mixed' + state + ending) # radio radio = Assets(20, 20, scl) radio.circle('shadow', 11, 11, 9) radio.circle(color2, 10, 10, 9) radio.circle(color1, 10, 10, 9, alpha=alpha) radio.circle(color2, 10, 10, 8) radio.save('radio-unchecked' + state + ending) if state != '': radio.circle(color1, 10, 10, 6, alpha=alpha) radio.save('radio-checked' + state + ending) radio.half_circle(color2, 10, 10, 4, alpha=alpha) radio.save('radio-mixed' + state + ending) # selectionmode selectionmode = Assets(40, 40, scl) selectionmode.rounded_rectancle('shadow', 18, 18, 12, 12, 3) selectionmode.rounded_rectancle(color2, 18, 18, 11, 11, 3) selectionmode.rounded_rectancle(color1, 18, 18, 11, 11, 3, alpha=alpha) selectionmode.rounded_rectancle(color2, 16, 16, 12, 12, 2) selectionmode.save('check-selectionmode-unchecked' + state + ending) if state != '': selectionmode.rounded_rectancle( color1, 12, 12, 14, 14, 1, alpha=alpha) selectionmode.save('check-selectionmode-checked' + state + ending) def buttons(color1, color2, color3, state, alpha=1.0): button = Assets(20, 20) button.rounded_rectancle('shadow', 18, 18, 2, 2, 3) button.rounded_rectancle(color1, 18, 18, 1, 1, 3) button.rounded_rectancle(color2, 18, 18, 1, 1, 3, alpha=alpha) if state == '-active': button.rounded_rectancle(color3, 18, 18, 1, 1, 3, gradient=True) else: button.rounded_rectancle(color1, 16, 16, 2, 2, 2) button.rounded_rectancle(color3, 16, 16, 2, 2, 2, gradient=True) button.save('button' + state + '.png') def togglebuttons(color1, color2, color3, state, alpha=1.0): button = Assets(20, 20) button.rounded_rectancle(color1, 18, 18, 1, 1, 3) button.rounded_rectancle(color2, 18, 18, 1, 1, 3, alpha=alpha) if state == '-active': button.rounded_rectancle(color3, 18, 18, 1, 1, 3, gradient=True) else: button.rounded_rectancle(color1, 16, 16, 2, 2, 2) button.rounded_rectancle(color3, 16, 16, 2, 2, 2, gradient=True) button.save('togglebutton' + state + '.png') def scale_slider(color1, color2, color3, state, alpha=1.0): scale = Assets(20, 20) scale.circle(color1, 10, 10, 10) scale.circle(color2, 10, 10, 10, alpha=alpha) scale.circle(color1, 10, 10, 9) scale.circle(color3, 10, 10, 9, gradient=True) scale.save('scale-slider' + state + '.png') def scale_trough(color): trough_h = Assets(20, 20) trough_h.rounded_rectancle(color, 20, 6, 0, 7, 3) trough_h.save('scale-trough-horizontal.png') trough_h = Assets(20, 20) trough_h.rounded_rectancle(color, 6, 20, 7, 0, 3) trough_h.save('scale-trough-vertical.png') def tabs(color1, color2, state): if state == '-inactive': alpha = 0.2 else: alpha = 1.0 direction = ['-bottom', '-left', '-top', '-right'] for i in range(0, 4): tab = Assets(20, 20, rotation=i) tab.tab(color1, 20, 20, 0, 0, 3, alpha) if state == '-active': tab.tab(color2, 18, 19, 1, 0, 2) tab.save('tab' + direction[i] + state + '.png') def arrows(color, state, alpha=1.0): direction = ['-up', '-right', '-down', '-left'] for i in range(0, 4): arw = Assets(12, 12, rotation=i) arw.arrow(color, alpha) arw.save('arrow' + direction[i] + state + '.png') arw = Assets(8, 8, rotation=i) arw.arrow_small(color, alpha) arw.save('arrow-small' + direction[i] + state + '.png') def menu_arrow(color, state, alpha=1.0): arrow = Assets(12, 12, rotation=1) arrow.arrow(color, alpha) arrow.save('menu-arrow' + state + '.png') def scrollbar_slider(color1, color2, color3): for scl in [1, 2]: if scl == 2: ending = '@2.png' else: ending = '.png' slider = Assets(30, 20, scl) slider.rounded_rectancle(color1, 30, 10, 0, 5, 5, 1) slider.save('scrollbar-slider-horizontal-active' + ending) slider = Assets(30, 20, scl) slider.rounded_rectancle(color2, 30, 6, 0, 7, 3, 1) slider.save('scrollbar-slider-horizontal-hover' + ending) slider = Assets(30, 20, scl) slider.rounded_rectancle(color3, 30, 6, 0, 7, 3, 1) slider.save('scrollbar-slider-horizontal' + ending) slider = Assets(20, 30, scl) slider.rounded_rectancle(color1, 10, 30, 5, 0, 5, 1) slider.save('scrollbar-slider-vertical-active' + ending) slider = Assets(20, 30, scl) slider.rounded_rectancle(color2, 6, 30, 7, 0, 3, 1) slider.save('scrollbar-slider-vertical-hover' + ending) slider = Assets(20, 30, scl) slider.rounded_rectancle(color3, 6, 30, 7, 0, 3, 1) slider.save('scrollbar-slider-vertical' + ending) def scrollbar_trough(color): for scl in [1, 2]: if scl == 2: ending = '@2.png' else: ending = '.png' trough = Assets(56, 20, scl) trough.rounded_rectancle(color, 49, 6, 3.5, 7, 3, 0.3) trough.save('scrollbar-trough-horizontal' + ending) trough = Assets(20, 56, scl) trough.rounded_rectancle(color, 6, 49, 7, 3.5, 3, 0.3) trough.save('scrollbar-trough-vertical' + ending) def titlebuttons(color1, color2, state): for scl in [1, 2]: if scl == 2: ending = '@2.png' else: ending = '.png' title_minimize = Assets(18, 18, scl) title_maximize = Assets(18, 18, scl) title_maximized = Assets(18, 18, scl) if state == '' or state == '-backdrop': title_minimize.minimize(color1) title_maximize.maximize(color1) title_maximized.maximize_maximized(color1) else: title_minimize.circle(color1, 9, 9, 9) title_maximize.circle(color1, 9, 9, 9) title_maximized.circle(color1, 9, 9, 9) title_minimize.minimize() title_maximize.maximize() title_maximized.maximize_maximized() title_minimize.save('titlebutton-minimize' + state + ending) title_maximize.save('titlebutton-maximize' + state + ending) title_maximized.save('titlebutton-maximize-maximized' + state + ending) title_close = Assets(18, 18, scl) title_close.circle(color2, 9, 9, 9) title_close.close() title_close.save('titlebutton-close' + state + ending) def entry(color1, color2, color3, state, alpha=1.0): entry = Assets(20, 20) entry.background(color1) entry.rounded_rectancle(color2, 18, 18, 1, 1, 3, alpha=alpha) entry.rounded_rectancle(color3, 16, 16, 2, 2, 2) entry.rounded_rectancle(color3, 16, 16, 2, 2, 2) entry.save('entry' + state + '.png') entry = Assets(20, 20, rotation=1) entry.background(color1) entry.tab(color2, 18, 19, 1, 0, 3, alpha=alpha) entry.tab(color3, 16, 18, 2, 0, 2) entry.save('combo-entry' + state + '.png') entry_button = Assets(20, 20, rotation=3) entry_button.background(color1) entry_button.tab(color2, 18, 19, 1, 0, 3, alpha=alpha) entry_button.tab(color3, 16, 18, 2, 0, 2) entry_button.save('combo-entry-button' + state + '.png') if state != '-active': direction = ['-down', '-down-rtl', '-up-rtl', '-up'] for i in range(0, 4): spin = Assets(20, 20, rotation=i) spin.background(color1) spin.spinbutton(color2, 19, 19, 0, 0, 3, alpha=alpha) spin.spinbutton(color3, 18, 18, 0, 0, 2) spin.save('spinbutton' + direction[i] + state + '.png') def mixed(color1, color2, color3): nll = Assets(20, 20) nll.save('null.png') # Frame frame = Assets(20, 20) frame.rounded_rectancle(color1, 20, 20, 0, 0, 3) frame.rounded_rectancle(color2, 18, 18, 1, 1, 2) frame.save('frame.png') # Tree header header = Assets(20, 20) header.background(color2) header.line(color1, 0, 19, 20, 1) header.line(color1, 19, 0, 1, 20) header.save('tree-header.png') # Notebook gap notebook_gap = Assets(4, 2) notebook_gap.line(color2, 1, 0, 2, 2) notebook_gap.save('notebook-gap-horizontal.png') notebook_gap = Assets(2, 4) notebook_gap.line(color2, 0, 1, 2, 2) notebook_gap.save('notebook-gap-vertical.png') # Notebook frame direction = ['-top', '-right', '-bottom', '-bottom'] for i in range(0, 4): notebook_frame = Assets(20, 20, rotation=i) notebook_frame.notebook(color1, 20, 20, 0, 0, 3) notebook_frame.notebook(color2, 18, 18, 1, 1, 2) notebook_frame.save('notebook-frame' + direction[i] + '.png') # Frame gap frame_gap = Assets(2, 1) frame_gap.line(color1, 1, 0, 1, 1) frame_gap.save('frame-gap-start.png') frame_gap = Assets(2, 1) frame_gap.line(color1, 0, 0, 1, 1) frame_gap.save('frame-gap-end.png') # Lines lines = Assets(20, 1) lines.line(color1, 0, 0, 20, 1) lines.save('line-h.png') lines = Assets(1, 20) lines.line(color1, 0, 0, 1, 20) lines.save('line-v.png') lines = Assets(20, 1) lines.line(color2, 0, 0, 20, 1) lines.save('handle-h.png') lines = Assets(1, 20) lines.line(color2, 0, 0, 1, 20) lines.save('handle-v.png') menubar = Assets(20, 20) menubar.line(color3, 1, 1, 18, 18) menubar.save('menubar-button.png') def toolbar(color1, color2, color3): # Toolbar background bar = Assets(20, 20) bar.background(color2) bar.save('toolbar-background.png') # Toolbutton toggled toolbutton = Assets(20, 20) toolbutton.rounded_rectancle(color1, 18, 18, 1, 1, 3) toolbutton.save('toolbutton-toggled.png') # Toolbutton hover toolbutton = Assets(20, 20) toolbutton.rounded_rectancle(color3, 18, 18, 1, 1, 3) toolbutton.rounded_rectancle(color2, 16, 16, 2, 2, 2) toolbutton.save('toolbutton-hover.png') # Toolbutton active toolbutton = Assets(20, 20) toolbutton.rounded_rectancle(color3, 18, 18, 1, 1, 3) toolbutton.save('toolbutton-active.png') def progressbar(color1, color2, state=''): bar = Assets(10, 10) bar.rounded_rectancle(color1, 10, 10, 0, 0, 3) bar.save('progressbar-bar' + state + '.png') trough = Assets(10, 10) trough.rounded_rectancle(color2, 10, 10, 0, 0, 3) trough.save('progressbar-trough' + state + '.png') def html(color): return '#%02x%02x%02x' % (int(color[0]*255), int(color[1]*255), int(color[2]*255)) def mix(color, mix_color, amount): r = color[0] * amount + mix_color[0] * (1 - amount) g = color[1] * amount + mix_color[1] * (1 - amount) b = color[2] * amount + mix_color[2] * (1 - amount) return (r, g, b) # ___________________________________________________________________________________ parser = argparse.ArgumentParser( description='Generates Breeze assets according to the specified color ' 'scheme.') parser.add_argument('--colorscheme', '-c', action='store', default='/usr/share/color-schemes/Breeze.colors', help='color scheme to use') parser.add_argument('--basecolorscheme', '-b', action='store', default='/usr/share/color-schemes/Breeze.colors', help='base color scheme') parser.add_argument('--assets-dir', '-a', action='store', default='assets', help='location of the directory to place assets') parser.add_argument('--gtk2-dir', '-g', action='store', default='gtk2', help='location of gtk2 directory to define the color ' 'scheme variables') parser.add_argument('--gtk3-scss-dir', '-G', action='store', default='.', help='location of global.scss to define the color ' 'scheme variables') args = parser.parse_args() assets_path = args.assets_dir make_sure_path_exists(assets_path) _colors = ReadKdeGlobals(args.basecolorscheme).read_globals(args.colorscheme) border_color = Color(_colors, 'WindowBackgroundNormal', 'WindowForegroundNormal', 0.75) window_bg = Color(_colors, 'WindowBackgroundNormal') window_fg = Color(_colors, 'WindowForegroundNormal') check_color = Color(_colors, 'WindowBackgroundNormal', 'WindowForegroundNormal', 0.5) button_bg = Color(_colors, 'ButtonBackgroundNormal') button_fg = Color(_colors, 'ButtonForegroundNormal') button_hover = Color(_colors, 'ButtonDecorationHover') button_active = Color(_colors, 'ButtonDecorationFocus') selection_bg = Color(_colors, 'SelectionBackgroundNormal') selection_fg = Color(_colors, 'SelectionForegroundNormal') view_bg = Color(_colors, 'ViewBackgroundNormal') view_fg = Color(_colors, 'ViewForegroundNormal') view_hover = Color(_colors, 'ViewDecorationHover') view_active = Color(_colors, 'ViewDecorationFocus') -titlebutton = Color(_colors, 'WindowForegroundNormal') -titlebutton_active = Color( - _colors, 'WindowBackgroundNormal', 'WindowForegroundNormal', 0.3) +titlebutton = Color(_colors, 'WMactiveForeground') +titlebutton_active = Color(_colors, 'WMactiveForeground') closebutton_hover = Color(_colors, 'ViewForegroundNegative') closebutton_hover.lighten_color(0.5) closebutton_active = Color(_colors, 'ViewForegroundNegative') -titlebutton_inactive = Color(_colors, 'WindowForegroundNormal') -titlebutton_inactive_active = Color( - _colors, 'WindowBackgroundNormal', 'WindowForegroundNormal', 0.3) - +titlebutton_inactive = Color(_colors, 'WMinactiveForeground') +titlebutton_inactive_active = Color(_colors, 'WMinactiveForeground') tooltip_fg = Color(_colors, 'TooltipForegroundNormal') tooltip_bg = Color(_colors, 'TooltipBackgroundNormal') check_items(check_color.rgb, window_bg.rgb, '') check_items(button_hover.rgb, window_bg.rgb, '-hover') check_items(button_active.rgb, window_bg.rgb, '-active') check_items(check_color.insensitive, window_bg.rgb, '-insensitive', border_color.insensitive_alpha) check_items(check_color.inactive, window_bg.rgb, '-backdrop', border_color.inactive_alpha) check_items(check_color.inactive_insensitive, window_bg.rgb, '-backdrop-insensitive', border_color.inactive_insensitive_alpha) buttons(window_bg.rgb, border_color.rgb, button_bg.gradient(), '') buttons(window_bg.rgb, button_hover.rgb, button_bg.gradient(), '-hover') buttons(window_bg.rgb, button_hover.rgb, button_hover.gradient('active'), '-active') buttons(window_bg.rgb, border_color.rgb, button_bg.gradient(alpha=button_bg.insensitive_alpha), '-insensitive', border_color.insensitive_alpha) togglebuttons(window_bg.rgb, border_color.rgb, button_bg.gradient(), '') togglebuttons(window_bg.rgb, button_hover.rgb, button_bg.gradient(), '-hover') togglebuttons(window_bg.rgb, button_hover.rgb, button_hover.gradient('active'), '-active') togglebuttons(window_bg.rgb, border_color.rgb, button_bg.gradient(alpha=button_bg.insensitive_alpha), '-insensitive', border_color.insensitive_alpha) scale_slider(window_bg.rgb, border_color.rgb, button_bg.gradient(), '') scale_slider(window_bg.rgb, button_hover.rgb, button_bg.gradient(), '-hover') scale_slider(window_bg.rgb, button_active.rgb, button_bg.gradient(), '-active') scale_slider(window_bg.rgb, border_color.rgb, button_bg.gradient(alpha=button_bg.insensitive_alpha), '-insensitive', border_color.insensitive_alpha) scale_trough(border_color.rgb) tabs(border_color.rgb, window_bg.rgb, '-active') tabs(window_fg.rgb, window_bg.rgb, '-inactive') arrows(button_fg.rgb, '') arrows(button_hover.rgb, '-hover') arrows(button_active.rgb, '-active') arrows(button_fg.insensitive, '-insensitive', button_fg.insensitive_alpha) menu_arrow(window_fg.rgb, '') menu_arrow(selection_fg.rgb, '-selected') menu_arrow(window_fg.insensitive, '-insensitive', window_fg.insensitive_alpha) scrollbar_slider(button_active.rgb, button_hover.rgb, button_active.rgb) scrollbar_trough(window_fg.rgb) titlebuttons(titlebutton.rgb, titlebutton.rgb, '') titlebuttons(titlebutton.rgb, closebutton_hover.rgb, '-hover') titlebuttons(titlebutton_active.rgb, closebutton_active.rgb, '-active') titlebuttons(titlebutton_inactive.rgb, titlebutton_inactive.rgb, '-backdrop') titlebuttons(titlebutton_inactive.rgb, closebutton_hover.rgb, '-hover-backdrop') titlebuttons(titlebutton_inactive_active.rgb, closebutton_active.rgb, '-active-backdrop') entry(window_bg.rgb, border_color.rgb, view_bg.rgb, '') entry(window_bg.rgb, view_active.rgb, view_bg.rgb, '-active') entry(window_bg.rgb, border_color.insensitive, None, '-insensitive', border_color.insensitive_alpha) progressbar(selection_bg.rgb, mix(window_fg.rgb, window_bg.rgb, 0.3)) mixed(border_color.rgb, window_bg.rgb, button_active.rgb) toolbar(border_color.rgb, window_bg.rgb, button_hover.rgb) gtk2 = open(os.path.join(args.gtk2_dir, 'gtkrc'), 'w') gtk2.write( '# Theme: Breeze-gtk\n' '# Description: Breeze theme for GTK+2.0\n' '\n' 'gtk-color-scheme = "text_color:' + html(window_fg.rgb) + '"\n' 'gtk-color-scheme = "base_color:' + html(view_bg.rgb) + '"\n' 'gtk-color-scheme = "insensitive_base_color:' + html(view_bg.insensitive) + '"\n' 'gtk-color-scheme = "fg_color:' + html(window_fg.rgb) + '"\n' 'gtk-color-scheme = "bg_color:' + html(window_bg.rgb) + '"\n' 'gtk-color-scheme = "selected_fg_color:' + html(selection_fg.rgb) + '"\n' 'gtk-color-scheme = "selected_bg_color:' + html(selection_bg.rgb) + '"\n' 'gtk-color-scheme = "button_fg_color:' + html(button_fg.rgb) + '"\n' 'gtk-color-scheme = "tooltip_fg_color:' + html(tooltip_fg.rgb) + '"\n' 'gtk-color-scheme = "tooltip_bg_color:' + html(tooltip_bg.rgb) + '"\n' 'gtk-color-scheme = "insensitive_fg_color:' + html(mix(window_fg.insensitive, window_bg.rgb, window_fg.insensitive_alpha)) + '"\n' 'gtk-color-scheme = "insensitive_text_color:' + html(mix(view_fg.insensitive, view_bg.rgb, view_fg.insensitive_alpha)) + '"\n' 'gtk-color-scheme = "button_insensitive_fg_color:' + html(mix(button_fg.insensitive, button_bg.rgb, button_fg.insensitive_alpha)) + '"\n' 'gtk-color-scheme = "button_active:' + html(button_active.rgb) + '"\n' 'gtk-color-scheme = "border_color:' + html(border_color.rgb) + '"\n' '\n' 'include "widgets/default"\n' 'include "widgets/buttons"\n' 'include "widgets/menu"\n' 'include "widgets/entry"\n' 'include "widgets/notebook"\n' 'include "widgets/range"\n' 'include "widgets/scrollbar"\n' 'include "widgets/toolbar"\n' 'include "widgets/progressbar"\n' 'include "widgets/misc"\n' 'include "widgets/styles"\n' ) gtk2.close() gtk3 = open(os.path.join(args.gtk3_scss_dir, '_global.scss'), 'w') for key in sorted(_colors): if key == 'DisabledColor' or key == 'InactiveColor': gtk3.write('${0}:rgb({1});\n'.format(key, _colors[key])) elif 'Disabled' in key or 'Inactive' in key: gtk3.write('${0}:{1};\n'.format(key, _colors[key])) elif re.match('[0-9]+,[0-9]+,[0-9]+', _colors[key]): gtk3.write('${0}:rgb({1});\n'.format(key, _colors[key])) gtk3.close()