From d58635bb3501b49221186e54fef79bf596d83cc0 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Sun, 29 Jan 2023 17:15:05 +0300
Subject: [PATCH 01/19] Add circle option
---
data/io.github.fsobolev.Cavalier.gschema.xml | 5 ++++
src/drawing_area.py | 1 +
src/preferences_window.py | 27 ++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 3e9acc3..82b15c4 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -37,6 +37,11 @@
"wave"
+
+ Circle
+ Whether to modify drawing modes to draw in circle
+ false
+
Drawing area margin
Size of gaps around drawing area (in pixels).
diff --git a/src/drawing_area.py b/src/drawing_area.py
index ade9fae..5b939d4 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -64,6 +64,7 @@ def run(self):
def on_settings_changed(self, key):
self.draw_mode = self.settings['mode']
+ self.circle = self.settings['circle']
self.set_margin_top(self.settings['margin'])
self.set_margin_bottom(self.settings['margin'])
self.set_margin_start(self.settings['margin'])
diff --git a/src/preferences_window.py b/src/preferences_window.py
index d303324..a897506 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -100,6 +100,26 @@ def create_cavalier_page(self):
self.bars_row.set_activatable_widget(self.bars_check_btn)
self.cavalier_mode_group.add(self.bars_row)
+ self.mode_variant_stack = Gtk.Stack.new()
+ self.mode_variant_stack.set_margin_top(24)
+ self.cavalier_mode_group.add(self.mode_variant_stack)
+
+ self.box_group = Adw.PreferencesGroup.new()
+ self.mode_variant_stack.add_titled(self.box_group, 'box', _('Box'))
+ self.mirror_row = Adw.ActionRow.new()
+ self.mirror_row.set_title(_('Mirror'))
+
+ self.circle_group = Adw.PreferencesGroup.new()
+ self.mode_variant_stack.add_titled(self.circle_group, 'circle', \
+ _('Circle'))
+ self.radius_row = Adw.ActionRow.new()
+ self.radius_row.set_title(_('Radius'))
+ self.circle_group.add(self.radius_row)
+
+ self.circle_switcher = Gtk.StackSwitcher.new()
+ self.circle_switcher.set_stack(self.mode_variant_stack)
+ self.cavalier_mode_group.set_header_suffix(self.circle_switcher)
+
self.cavalier_group = Adw.PreferencesGroup.new()
self.cavalier_page.add(self.cavalier_group)
@@ -412,6 +432,8 @@ def load_settings(self):
self.particles_check_btn, self.spine_check_btn, self.bars_check_btn)[ \
self.settings.get_range('mode')[1].index(self.settings['mode']) \
].set_active(True)
+ self.mode_variant_stack.set_visible_child_name( \
+ 'circle' if self.settings['circle'] else 'box')
self.pref_margin_scale.set_value(self.settings['margin'])
self.pref_offset_scale.set_value(self.settings['items-offset'])
self.pref_roundness_scale.set_value( \
@@ -471,6 +493,11 @@ def bind_settings(self):
'particles')
self.spine_check_btn.connect('toggled', self.change_mode, 'spine')
self.bars_check_btn.connect('toggled', self.change_mode, 'bars')
+ # `notify::visible-child` signal returns additional parameter that
+ # we don't need, that's why lambda is used.
+ self.mode_variant_stack.connect('notify::visible-child', \
+ lambda *args: self.save_setting(self.mode_variant_stack, 'circle', \
+ self.mode_variant_stack.get_visible_child_name() == 'circle'))
self.pref_margin_scale.connect('value-changed', self.save_setting, \
'margin', self.pref_margin_scale.get_value)
self.pref_offset_scale.connect('value-changed', self.save_setting, \
From 61afd5de9290595cdd5dd0265e9cde0afc49e10d Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Sun, 29 Jan 2023 19:04:33 +0300
Subject: [PATCH 02/19] Implement Line mode Circle variant
---
src/drawing_area.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/drawing_area.py b/src/drawing_area.py
index 5b939d4..183e929 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -31,7 +31,7 @@
from gi.repository import Gtk, GObject
from threading import Thread
from cavalier.cava import Cava
-from cavalier.draw_functions import wave, levels, particles, spine, bars
+from cavalier.draw_functions import *
from cavalier.settings import CavalierSettings
class CavalierDrawingArea(Gtk.DrawingArea):
From bd130348cccbeaad24b839524bc935bfc0e15e41 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Tue, 31 Jan 2023 03:30:31 +0300
Subject: [PATCH 03/19] Implement radius setting
---
data/io.github.fsobolev.Cavalier.gschema.xml | 6 ++++++
src/drawing_area.py | 1 +
src/preferences_window.py | 16 +++++++++++++---
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 82b15c4..14eaa26 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -42,6 +42,12 @@
Whether to modify drawing modes to draw in circle
false
+
+ Radius
+ Radius of base circle (in percent)
+
+ 20
+
Drawing area margin
Size of gaps around drawing area (in pixels).
diff --git a/src/drawing_area.py b/src/drawing_area.py
index 183e929..abad1b6 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -65,6 +65,7 @@ def run(self):
def on_settings_changed(self, key):
self.draw_mode = self.settings['mode']
self.circle = self.settings['circle']
+ self.radius = self.settings['radius']
self.set_margin_top(self.settings['margin'])
self.set_margin_bottom(self.settings['margin'])
self.set_margin_start(self.settings['margin'])
diff --git a/src/preferences_window.py b/src/preferences_window.py
index a897506..ec7ce6d 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -112,9 +112,16 @@ def create_cavalier_page(self):
self.circle_group = Adw.PreferencesGroup.new()
self.mode_variant_stack.add_titled(self.circle_group, 'circle', \
_('Circle'))
- self.radius_row = Adw.ActionRow.new()
- self.radius_row.set_title(_('Radius'))
- self.circle_group.add(self.radius_row)
+ self.pref_radius = Adw.ActionRow.new()
+ self.pref_radius.set_title(_('Radius'))
+ self.pref_radius.set_subtitle(_('Radius of base circle (in percent)'))
+ self.pref_radius_scale = Gtk.Scale.new_with_range( \
+ Gtk.Orientation.HORIZONTAL, 0.0, 50.0, 1.0)
+ self.pref_radius_scale.set_size_request(180, -1)
+ self.pref_radius_scale.set_draw_value(True)
+ self.pref_radius_scale.set_value_pos(Gtk.PositionType.LEFT)
+ self.pref_radius.add_suffix(self.pref_radius_scale)
+ self.circle_group.add(self.pref_radius)
self.circle_switcher = Gtk.StackSwitcher.new()
self.circle_switcher.set_stack(self.mode_variant_stack)
@@ -434,6 +441,7 @@ def load_settings(self):
].set_active(True)
self.mode_variant_stack.set_visible_child_name( \
'circle' if self.settings['circle'] else 'box')
+ self.pref_radius_scale.set_value(self.settings['radius'])
self.pref_margin_scale.set_value(self.settings['margin'])
self.pref_offset_scale.set_value(self.settings['items-offset'])
self.pref_roundness_scale.set_value( \
@@ -498,6 +506,8 @@ def bind_settings(self):
self.mode_variant_stack.connect('notify::visible-child', \
lambda *args: self.save_setting(self.mode_variant_stack, 'circle', \
self.mode_variant_stack.get_visible_child_name() == 'circle'))
+ self.pref_radius_scale.connect('value-changed', self.save_setting, \
+ 'radius', self.pref_radius_scale.get_value)
self.pref_margin_scale.connect('value-changed', self.save_setting, \
'margin', self.pref_margin_scale.get_value)
self.pref_offset_scale.connect('value-changed', self.save_setting, \
From b8c1a9fd47f7479f1805fd403d1643145f45b1f3 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Tue, 31 Jan 2023 04:02:49 +0300
Subject: [PATCH 04/19] Radial gradient
---
src/draw_functions.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index f198166..9dc560a 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -44,6 +44,18 @@ def set_source(cr, height, colors, offset=0):
(red, green, blue, alpha) = colors[0]
cr.set_source_rgba(red / 255, green / 255, blue / 255, alpha)
+def set_source_radial(cr, x, y, r0, r1, colors):
+ if len(colors) > 1:
+ pat = cairo.RadialGradient(x, y, r0, x, y, r1)
+ for i in range(len(colors)):
+ (red, green, blue, alpha) = colors[i]
+ pat.add_color_stop_rgba(1 / (i + 1), \
+ red / 255, green / 255, blue / 255, alpha)
+ cr.set_source(pat)
+ else:
+ (red, green, blue, alpha) = colors[0]
+ cr.set_source_rgba(red / 255, green / 255, blue / 255, alpha)
+
def draw_element(cr, x, y, width, height, radius):
degrees = math.pi / 180.0
cr.new_sub_path()
From a14206c3c690e243f14cfee2b66427403820cbbf Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Tue, 31 Jan 2023 05:06:06 +0300
Subject: [PATCH 05/19] Wave mode Circle variant
---
src/draw_functions.py | 53 +++++++++++++++++++++++++++++++++++++++++++
src/drawing_area.py | 8 +++++--
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 9dc560a..92e8dc6 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -86,6 +86,59 @@ def wave(sample, cr, width, height, colors, fill, thickness):
cr.set_line_width(thickness)
cr.stroke()
+def wave_circle(sample, cr, width, height, colors, radius, thickness):
+ ls = len(sample)
+ cr.move_to(width / 2, height / 2)
+ min_radius = min(width, height) * radius / 200
+ max_radius = min(width, height) / 2
+ set_source_radial(cr, width / 2, height / 2, min_radius, \
+ max_radius + thickness, colors)
+ cr.rectangle(0, 0, width, height)
+ cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, 2 * math.pi, 0)
+ cr.clip()
+ cr.new_path()
+ cr.move_to(width / 2 + min_radius, height / 2)
+ cr.arc(width / 2, height / 2, min_radius, 0, 2 * math.pi)
+ cr.set_line_width(thickness)
+ cr.stroke()
+ cr.move_to( \
+ width / 2 + math.cos(2 * math.pi / ls * (ls - 0.5) - 0.5 * math.pi) * \
+ (min_radius + sample[-1] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (ls - 0.5) - 0.5 * math.pi) * \
+ (min_radius + sample[-1] * (max_radius - min_radius))
+ )
+ cr.curve_to( \
+ width / 2 + math.cos(2 * math.pi / ls * (0) - 0.5 * math.pi) * \
+ (min_radius + sample[-1] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (0) - 0.5 * math.pi) * \
+ (min_radius + sample[-1] * (max_radius - min_radius)), \
+ width / 2 + math.cos(2 * math.pi / ls * (0) - 0.5 * math.pi) * \
+ (min_radius + sample[0] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (0) - 0.5 * math.pi) * \
+ (min_radius + sample[0] * (max_radius - min_radius)), \
+ width / 2 + math.cos(2 * math.pi / ls * (0.5) - 0.5 * math.pi) * \
+ (min_radius + sample[0] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (0.5) - 0.5 * math.pi) * \
+ (min_radius + sample[0] * (max_radius - min_radius))
+ )
+ for i in range(ls - 1):
+ cr.curve_to( \
+ width / 2 + math.cos(2 * math.pi / ls * (i + 1) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (i + 1) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)), \
+ width / 2 + math.cos(2 * math.pi / ls * (i + 1) - 0.5 * math.pi) * \
+ (min_radius + sample[i+1] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (i + 1) - 0.5 * math.pi) * \
+ (min_radius + sample[i+1] * (max_radius - min_radius)), \
+ width / 2 + math.cos(2 * math.pi / ls * (i + 1.5) - 0.5 * math.pi) * \
+ (min_radius + sample[i+1] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * (i + 1.5) - 0.5 * math.pi) * \
+ (min_radius + sample[i+1] * (max_radius - min_radius))
+ )
+ cr.close_path() # required to avoid artifact with thick lines
+ cr.fill()
+
def levels(sample, cr, width, height, colors, offset, radius, fill, thickness):
set_source(cr, height, colors)
ls = len(sample)
diff --git a/src/drawing_area.py b/src/drawing_area.py
index abad1b6..35cce8a 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -100,8 +100,12 @@ def on_settings_changed(self, key):
def draw_func(self, area, cr, width, height, data, n):
if len(self.cava_sample) > 0:
if self.draw_mode == 'wave':
- wave(self.cava_sample, cr, width, height, self.colors, \
- self.fill, self.thickness)
+ if self.circle:
+ wave_circle(self.cava_sample, cr, width, height, \
+ self.colors, self.radius, self.thickness)
+ else:
+ wave(self.cava_sample, cr, width, height, self.colors, \
+ self.fill, self.thickness)
elif self.draw_mode == 'levels':
levels(self.cava_sample, cr, width, height, self.colors, \
self.offset, self.roundness, self.fill, self.thickness)
From dfd18fdefe6017be4fb3ef422f0d70f144cfd33a Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Thu, 2 Feb 2023 04:03:32 +0300
Subject: [PATCH 06/19] Wave Circle Fill Option
---
data/io.github.fsobolev.Cavalier.gschema.xml | 5 +++++
src/draw_functions.py | 19 ++++++++++---------
src/drawing_area.py | 4 +++-
src/preferences_window.py | 13 +++++++++++++
4 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 14eaa26..b1a4ab7 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -42,6 +42,11 @@
Whether to modify drawing modes to draw in circle
false
+
+ Wave - Fill Circle
+ Whether to fill the inner circle when using Wave mode Circle variant.
+ false
+
Radius
Radius of base circle (in percent)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 92e8dc6..c1bcf88 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -86,21 +86,22 @@ def wave(sample, cr, width, height, colors, fill, thickness):
cr.set_line_width(thickness)
cr.stroke()
-def wave_circle(sample, cr, width, height, colors, radius, thickness):
+def wave_circle(sample, cr, width, height, colors, radius, thickness, fill):
ls = len(sample)
cr.move_to(width / 2, height / 2)
min_radius = min(width, height) * radius / 200
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, \
max_radius + thickness, colors)
- cr.rectangle(0, 0, width, height)
- cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, 2 * math.pi, 0)
- cr.clip()
- cr.new_path()
- cr.move_to(width / 2 + min_radius, height / 2)
- cr.arc(width / 2, height / 2, min_radius, 0, 2 * math.pi)
- cr.set_line_width(thickness)
- cr.stroke()
+ if not fill:
+ cr.rectangle(0, 0, width, height)
+ cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, 2 * math.pi, 0)
+ cr.clip()
+ cr.new_path()
+ cr.move_to(width / 2 + min_radius, height / 2)
+ cr.arc(width / 2, height / 2, min_radius, 0, 2 * math.pi)
+ cr.set_line_width(thickness)
+ cr.stroke()
cr.move_to( \
width / 2 + math.cos(2 * math.pi / ls * (ls - 0.5) - 0.5 * math.pi) * \
(min_radius + sample[-1] * (max_radius - min_radius)), \
diff --git a/src/drawing_area.py b/src/drawing_area.py
index 35cce8a..2db0c51 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -65,6 +65,7 @@ def run(self):
def on_settings_changed(self, key):
self.draw_mode = self.settings['mode']
self.circle = self.settings['circle']
+ self.wave_circle_fill = self.settings['wave-circle-fill']
self.radius = self.settings['radius']
self.set_margin_top(self.settings['margin'])
self.set_margin_bottom(self.settings['margin'])
@@ -102,7 +103,8 @@ def draw_func(self, area, cr, width, height, data, n):
if self.draw_mode == 'wave':
if self.circle:
wave_circle(self.cava_sample, cr, width, height, \
- self.colors, self.radius, self.thickness)
+ self.colors, self.radius, self.thickness, \
+ self.wave_circle_fill)
else:
wave(self.cava_sample, cr, width, height, self.colors, \
self.fill, self.thickness)
diff --git a/src/preferences_window.py b/src/preferences_window.py
index ec7ce6d..f6894a4 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -66,6 +66,13 @@ def create_cavalier_page(self):
self.wave_check_btn = Gtk.CheckButton.new()
self.wave_row.add_prefix(self.wave_check_btn)
self.wave_row.set_activatable_widget(self.wave_check_btn)
+ self.wave_circle_fill_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10)
+ self.wave_row.add_suffix(self.wave_circle_fill_box)
+ self.wave_circle_fill_label = Gtk.Label.new(_('Fill completely'))
+ self.wave_circle_fill_box.append(self.wave_circle_fill_label)
+ self.wave_circle_fill_switch = Gtk.Switch.new()
+ self.wave_circle_fill_switch.set_valign(Gtk.Align.CENTER)
+ self.wave_circle_fill_box.append(self.wave_circle_fill_switch)
self.cavalier_mode_group.add(self.wave_row)
self.levels_row = Adw.ActionRow.new()
@@ -441,6 +448,9 @@ def load_settings(self):
].set_active(True)
self.mode_variant_stack.set_visible_child_name( \
'circle' if self.settings['circle'] else 'box')
+ self.wave_circle_fill_box.set_visible(self.settings['circle'])
+ self.wave_circle_fill_switch.set_active( \
+ self.settings['wave-circle-fill'])
self.pref_radius_scale.set_value(self.settings['radius'])
self.pref_margin_scale.set_value(self.settings['margin'])
self.pref_offset_scale.set_value(self.settings['items-offset'])
@@ -496,6 +506,9 @@ def load_settings(self):
def bind_settings(self):
self.wave_check_btn.connect('toggled', self.change_mode, 'wave')
+ self.wave_circle_fill_switch.connect('notify::state', \
+ lambda *args : self.save_setting(self.wave_circle_fill_switch, \
+ 'wave-circle-fill', self.wave_circle_fill_switch.get_state()))
self.levels_check_btn.connect('toggled', self.change_mode, 'levels')
self.particles_check_btn.connect('toggled', self.change_mode, \
'particles')
From 721b0e59131d8935978f3ea0d8b1579253b3dfc4 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Thu, 2 Feb 2023 04:25:52 +0300
Subject: [PATCH 07/19] Fix radial gradient
---
src/draw_functions.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index c1bcf88..8fd8714 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -92,10 +92,11 @@ def wave_circle(sample, cr, width, height, colors, radius, thickness, fill):
min_radius = min(width, height) * radius / 200
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, \
- max_radius + thickness, colors)
+ max_radius, colors)
if not fill:
cr.rectangle(0, 0, width, height)
- cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, 2 * math.pi, 0)
+ cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, \
+ 2 * math.pi, 0)
cr.clip()
cr.new_path()
cr.move_to(width / 2 + min_radius, height / 2)
From 4233a5e9ab6c1d27ab2157e7e2b58424e683e411 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Thu, 2 Feb 2023 06:12:05 +0300
Subject: [PATCH 08/19] Bars mode Circle variant
---
src/draw_functions.py | 38 ++++++++++++++++++++++++++++++++++++++
src/drawing_area.py | 8 ++++++--
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 8fd8714..99bcf2d 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -229,3 +229,41 @@ def bars(sample, cr, width, height, colors, offset, fill, thickness):
height - height * sample[i] + thickness / 2, \
max(step - offset_px * 2 - thickness, 1), height * sample[i] - thickness)
cr.fill() if fill else cr.stroke()
+
+def bars_circle(sample, cr, width, height, colors, offset, radius):
+ ls = len(sample)
+ min_radius = min(width, height) * radius / 200
+ max_radius = min(width, height) / 2
+ set_source_radial(cr, width / 2, height / 2, min_radius, max_radius, colors)
+ for i in range(ls):
+ cr.move_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + offset / 100) - 0.5 * math.pi) * min_radius, \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + offset / 100) - 0.5 * math.pi) * min_radius)
+ cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + offset / 100) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + offset / 100) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)))
+ cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)))
+ cr.move_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + offset / 100) - 0.5 * math.pi) * min_radius, \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + offset / 100) - 0.5 * math.pi) * min_radius)
+ cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius, \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius)
+ cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)), \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * \
+ (min_radius + sample[i] * (max_radius - min_radius)))
+ cr.fill()
diff --git a/src/drawing_area.py b/src/drawing_area.py
index 2db0c51..dfef253 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -118,8 +118,12 @@ def draw_func(self, area, cr, width, height, data, n):
spine(self.cava_sample, cr, width, height, self.colors, \
self.offset, self.roundness, self.fill, self.thickness)
elif self.draw_mode == 'bars':
- bars(self.cava_sample, cr, width, height, self.colors, \
- self.offset, self.fill, self.thickness)
+ if self.circle:
+ bars_circle(self.cava_sample, cr, width, height, \
+ self.colors, self.offset, self.radius)
+ else:
+ bars(self.cava_sample, cr, width, height, self.colors, \
+ self.offset, self.fill, self.thickness)
def redraw(self):
self.queue_draw()
From 833e4754ed9aae7e45719cd33545e97e458e9efe Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Thu, 2 Feb 2023 07:10:06 +0300
Subject: [PATCH 09/19] Bars fill setting
---
data/io.github.fsobolev.Cavalier.gschema.xml | 10 +++++++++
src/draw_functions.py | 23 +++++++++++---------
src/drawing_area.py | 4 +++-
src/preferences_window.py | 19 ++++++++++++----
4 files changed, 41 insertions(+), 15 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index b1a4ab7..2b976d2 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -37,6 +37,16 @@
"wave"
+
+ Bars Filling
+ Filling rule for Bars drawing mode
+
+
+
+
+
+ "bars"
+
Circle
Whether to modify drawing modes to draw in circle
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 99bcf2d..d5370fb 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -216,6 +216,7 @@ def spine(sample, cr, width, height, colors, offset, radius, fill, thickness):
def bars(sample, cr, width, height, colors, offset, fill, thickness):
set_source(cr, height, colors)
+ cr.set_line_width(thickness)
ls = len(sample)
step = width / ls
offset_px = step * offset / 100
@@ -230,11 +231,13 @@ def bars(sample, cr, width, height, colors, offset, fill, thickness):
max(step - offset_px * 2 - thickness, 1), height * sample[i] - thickness)
cr.fill() if fill else cr.stroke()
-def bars_circle(sample, cr, width, height, colors, offset, radius):
+def bars_circle(sample, cr, width, height, colors, offset, fill, thickness, \
+ radius):
ls = len(sample)
min_radius = min(width, height) * radius / 200
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, max_radius, colors)
+ cr.set_line_width(thickness)
for i in range(ls):
cr.move_to(width / 2 + math.cos(2 * math.pi / ls * \
(i + offset / 100) - 0.5 * math.pi) * min_radius, \
@@ -252,18 +255,18 @@ def bars_circle(sample, cr, width, height, colors, offset, radius):
height / 2 + math.sin(2 * math.pi / ls * \
(i + 1 - offset / 100) - 0.5 * math.pi) * \
(min_radius + sample[i] * (max_radius - min_radius)))
- cr.move_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + offset / 100) - 0.5 * math.pi) * min_radius, \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + offset / 100) - 0.5 * math.pi) * min_radius)
- cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius, \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius)
cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
(i + 1 - offset / 100) - 0.5 * math.pi) * \
(min_radius + sample[i] * (max_radius - min_radius)), \
height / 2 + math.sin(2 * math.pi / ls * \
(i + 1 - offset / 100) - 0.5 * math.pi) * \
(min_radius + sample[i] * (max_radius - min_radius)))
- cr.fill()
+ cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius, \
+ height / 2 + math.sin(2 * math.pi / ls * \
+ (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius)
+ cr.close_path()
+ if fill == "all":
+ cr.move_to(width / 2 + min_radius, height / 2)
+ cr.arc(width / 2, height / 2, min_radius, 0, 2 * math.pi)
+ cr.stroke() if fill == "outline" else cr.fill()
diff --git a/src/drawing_area.py b/src/drawing_area.py
index dfef253..266a7b7 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -64,6 +64,7 @@ def run(self):
def on_settings_changed(self, key):
self.draw_mode = self.settings['mode']
+ self.bars_fill = self.settings['bars-fill']
self.circle = self.settings['circle']
self.wave_circle_fill = self.settings['wave-circle-fill']
self.radius = self.settings['radius']
@@ -120,7 +121,8 @@ def draw_func(self, area, cr, width, height, data, n):
elif self.draw_mode == 'bars':
if self.circle:
bars_circle(self.cava_sample, cr, width, height, \
- self.colors, self.offset, self.radius)
+ self.colors, self.offset, self.bars_fill, \
+ self.thickness, self.radius)
else:
bars(self.cava_sample, cr, width, height, self.colors, \
self.offset, self.fill, self.thickness)
diff --git a/src/preferences_window.py b/src/preferences_window.py
index f6894a4..738c2f5 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -48,7 +48,7 @@ def __init__(self, **kwargs):
self.create_cava_page()
self.create_colors_page()
self.settings_bind = False
- self.do_not_change_profile = False
+ self.do_not_update = False
self.load_settings()
def create_cavalier_page(self):
@@ -105,6 +105,10 @@ def create_cavalier_page(self):
self.bars_check_btn.set_group(self.wave_check_btn)
self.bars_row.add_prefix(self.bars_check_btn)
self.bars_row.set_activatable_widget(self.bars_check_btn)
+ self.bars_fill_dropdown = Gtk.DropDown.new_from_strings( \
+ [_('Outline'), _('Fill bars'), _('Fill bars and circle')])
+ self.bars_fill_dropdown.set_valign(Gtk.Align.CENTER)
+ self.bars_row.add_suffix(self.bars_fill_dropdown)
self.cavalier_mode_group.add(self.bars_row)
self.mode_variant_stack = Gtk.Stack.new()
@@ -442,10 +446,14 @@ def create_colors_page(self):
self.bg_color_btns = []
def load_settings(self):
+ self.do_not_update = True
(self.wave_check_btn, self.levels_check_btn, \
self.particles_check_btn, self.spine_check_btn, self.bars_check_btn)[ \
self.settings.get_range('mode')[1].index(self.settings['mode']) \
].set_active(True)
+ self.bars_fill_dropdown.set_selected( \
+ self.settings.get_range('bars-fill')[1].index( \
+ self.settings['bars-fill']))
self.mode_variant_stack.set_visible_child_name( \
'circle' if self.settings['circle'] else 'box')
self.wave_circle_fill_box.set_visible(self.settings['circle'])
@@ -487,7 +495,6 @@ def load_settings(self):
self.bind_settings()
profiles = self.settings['color-profiles']
active_profile = self.settings['active-color-profile']
- self.do_not_change_profile = True
while self.profiles_list.get_n_items() > 0:
self.profiles_list.remove(0)
for p in profiles:
@@ -498,11 +505,11 @@ def load_settings(self):
except:
self.settings['active-color-profile'] = 0
return
- self.do_not_change_profile = False
self.profiles_dropdown.set_selected(active_profile)
self.profile_remove_button.set_sensitive(active_profile != 0)
self.clear_colors_grid()
self.fill_colors_grid()
+ self.do_not_update = False
def bind_settings(self):
self.wave_check_btn.connect('toggled', self.change_mode, 'wave')
@@ -514,6 +521,10 @@ def bind_settings(self):
'particles')
self.spine_check_btn.connect('toggled', self.change_mode, 'spine')
self.bars_check_btn.connect('toggled', self.change_mode, 'bars')
+ self.bars_fill_dropdown.connect('notify::selected-item', \
+ lambda *args: self.save_setting(self.bars_fill_dropdown, \
+ 'bars-fill', self.settings.get_range('bars-fill')[1][ \
+ self.bars_fill_dropdown.get_selected()]))
# `notify::visible-child` signal returns additional parameter that
# we don't need, that's why lambda is used.
self.mode_variant_stack.connect('notify::visible-child', \
@@ -686,7 +697,7 @@ def clear_colors_grid(self):
break
def select_color_profile(self, obj, pos):
- if self.do_not_change_profile:
+ if self.do_not_update:
return
if self.profiles_dropdown.get_selected() != \
self.settings['active-color-profile']:
From f915ac2769c52c875717fb7bded3b7f506511539 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Thu, 2 Feb 2023 07:20:50 +0300
Subject: [PATCH 10/19] Wave Circle - Fix min radius when not filled
---
src/draw_functions.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index d5370fb..3e142ad 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -103,6 +103,7 @@ def wave_circle(sample, cr, width, height, colors, radius, thickness, fill):
cr.arc(width / 2, height / 2, min_radius, 0, 2 * math.pi)
cr.set_line_width(thickness)
cr.stroke()
+ min_radius += thickness
cr.move_to( \
width / 2 + math.cos(2 * math.pi / ls * (ls - 0.5) - 0.5 * math.pi) * \
(min_radius + sample[-1] * (max_radius - min_radius)), \
From 0185b2505c9d80735cdedb1f93a0893a99a74b2d Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Fri, 3 Feb 2023 07:43:27 +0300
Subject: [PATCH 11/19] Rework radius setting
---
data/io.github.fsobolev.Cavalier.gschema.xml | 4 ++--
src/draw_functions.py | 4 ++--
src/preferences_window.py | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 2b976d2..c4a48ab 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -60,8 +60,8 @@
Radius
Radius of base circle (in percent)
-
- 20
+
+ 40
Drawing area margin
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 3e142ad..1ce4aca 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -89,7 +89,7 @@ def wave(sample, cr, width, height, colors, fill, thickness):
def wave_circle(sample, cr, width, height, colors, radius, thickness, fill):
ls = len(sample)
cr.move_to(width / 2, height / 2)
- min_radius = min(width, height) * radius / 200
+ min_radius = min(width, height) * radius / 400
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, \
max_radius, colors)
@@ -235,7 +235,7 @@ def bars(sample, cr, width, height, colors, offset, fill, thickness):
def bars_circle(sample, cr, width, height, colors, offset, fill, thickness, \
radius):
ls = len(sample)
- min_radius = min(width, height) * radius / 200
+ min_radius = min(width, height) * radius / 400
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, max_radius, colors)
cr.set_line_width(thickness)
diff --git a/src/preferences_window.py b/src/preferences_window.py
index 738c2f5..8eb3bff 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -127,7 +127,7 @@ def create_cavalier_page(self):
self.pref_radius.set_title(_('Radius'))
self.pref_radius.set_subtitle(_('Radius of base circle (in percent)'))
self.pref_radius_scale = Gtk.Scale.new_with_range( \
- Gtk.Orientation.HORIZONTAL, 0.0, 50.0, 1.0)
+ Gtk.Orientation.HORIZONTAL, 0.0, 100.0, 1.0)
self.pref_radius_scale.set_size_request(180, -1)
self.pref_radius_scale.set_draw_value(True)
self.pref_radius_scale.set_value_pos(Gtk.PositionType.LEFT)
From 9aa8bb9a78f1d2d9c856f343b3bd27a6cbe20691 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Fri, 3 Feb 2023 11:54:49 +0300
Subject: [PATCH 12/19] Impove draw_element, particles and spine
draw_element now acceps center coordinates instead of top left corner, making it easier to use with circle variants.
Also gradients are now better applied in Spine mode
---
data/io.github.fsobolev.Cavalier.gschema.xml | 4 +--
src/draw_functions.py | 34 +++++++++++---------
src/preferences_window.py | 6 ++--
3 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index c4a48ab..3d4786d 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -78,8 +78,8 @@
Roundness of items
This setting affects "levels", "particles" and "spine" modes.
-
- 10
+
+ 20
Thickness of lines
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 1ce4aca..b8f1b0a 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -57,16 +57,21 @@ def set_source_radial(cr, x, y, r0, r1, colors):
cr.set_source_rgba(red / 255, green / 255, blue / 255, alpha)
def draw_element(cr, x, y, width, height, radius):
- degrees = math.pi / 180.0
+ width /= 2
+ height /= 2
cr.new_sub_path()
- cr.arc(x + width * radius / 100, y + height * radius / 100, \
- radius * min(width, height) / 100, -180 * degrees, -90 * degrees)
- cr.arc(x + width - width * radius / 100, y + height * radius / 100, \
- radius * min(width, height) / 100, -90 * degrees, 0)
- cr.arc(x + width - width * radius / 100, y + height - height * radius / 100, \
- radius * min(width, height) / 100, 0, 90 * degrees)
- cr.arc(x + width * radius / 100, y + height - height * radius / 100, \
- radius * min(width, height) / 100, 90 * degrees, -180 * degrees)
+ cr.arc(x + width - width * radius / 100, \
+ y + height - height * radius / 100, \
+ radius * min(width, height) / 100, 0, 0.5 * math.pi)
+ cr.arc(x - width + width * radius / 100, \
+ y + height - height * radius / 100, \
+ radius * min(width, height) / 100, 0.5 * math.pi, math.pi)
+ cr.arc(x - width + width * radius / 100, \
+ y - height + height * radius / 100, \
+ radius * min(width, height) / 100, math.pi, 1.5 * math.pi)
+ cr.arc(x + width - width * radius / 100, \
+ y - height + height * radius / 100, \
+ radius * min(width, height) / 100, 1.5 * math.pi, 0)
cr.close_path()
def wave(sample, cr, width, height, colors, fill, thickness):
@@ -176,8 +181,8 @@ def particles(sample, cr, width, height, colors, offset, radius, fill, thickness
(height / 10) / 2)
cr.set_line_width(thickness)
for i in range(ls):
- draw_element(cr, step * i + offset_px + thickness / 2, \
- height * 0.9 - height * 0.9 * sample[i] + thickness / 2, \
+ draw_element(cr, step * (i + 0.5), \
+ height * 0.95 - (height * 0.9) * sample[i], \
max(step - offset_px * 2 - thickness, 1), \
max(height / 10 - thickness, 1), radius)
cr.fill() if fill else cr.stroke()
@@ -196,8 +201,7 @@ def spine(sample, cr, width, height, colors, offset, radius, fill, thickness):
thickness = min(thickness, \
(step * sample[i] - offset_px * 2) / 2)
cr.set_line_width(thickness)
- draw_element(cr, width / 2 - sample[i] * step / 2 + offset_px + thickness / 2, \
- step * i + step / 2 - sample[i] * step / 2 + offset_px + thickness / 2, \
+ draw_element(cr, width / 2, step * (i + 0.5), \
step * sample[i] - offset_px * 2 - thickness, \
step * sample[i] - offset_px * 2 - thickness, radius)
cr.fill() if fill else cr.stroke()
@@ -208,9 +212,7 @@ def spine(sample, cr, width, height, colors, offset, radius, fill, thickness):
offset_px = step * offset / 100 * sample[i]
if not fill:
offset_px += thickness / 2
- draw_element(cr, \
- step * i + step / 2 - sample[i] * step / 2 + offset_px, \
- height / 2 - sample[i] * step / 2 + offset_px, \
+ draw_element(cr, step * (i + 0.5), height / 2,
step * sample[i] - offset_px * 2, \
step * sample[i] - offset_px * 2, radius)
cr.fill() if fill else cr.stroke()
diff --git a/src/preferences_window.py b/src/preferences_window.py
index 8eb3bff..4af5424 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -170,7 +170,7 @@ def create_cavalier_page(self):
self.pref_roundness.set_subtitle( \
_('This setting affects "levels", "particles" and "spine" modes.\n0 - square, 1 - round'))
self.pref_roundness_scale = Gtk.Scale.new_with_range( \
- Gtk.Orientation.HORIZONTAL, 0.0, 1.0, 0.02)
+ Gtk.Orientation.HORIZONTAL, 0.0, 1.0, 0.01)
self.pref_roundness_scale.set_size_request(190, -1)
self.pref_roundness_scale.set_draw_value(True)
self.pref_roundness_scale.set_value_pos(Gtk.PositionType.LEFT)
@@ -463,7 +463,7 @@ def load_settings(self):
self.pref_margin_scale.set_value(self.settings['margin'])
self.pref_offset_scale.set_value(self.settings['items-offset'])
self.pref_roundness_scale.set_value( \
- round(self.settings['items-roundness'] / 50.0, 2))
+ round(self.settings['items-roundness'] / 100.0, 2))
self.pref_thickness_scale.set_value(self.settings['line-thickness'])
self.pref_fill_switch.set_active(self.settings['fill'])
self.pref_borderless_switch.set_active( \
@@ -538,7 +538,7 @@ def bind_settings(self):
'items-offset', self.pref_offset_scale.get_value)
self.pref_roundness_scale.connect('value-changed', self.save_setting, \
'items-roundness', lambda *args : \
- self.pref_roundness_scale.get_value() * 50.0)
+ self.pref_roundness_scale.get_value() * 100.0)
self.pref_thickness_scale.connect('value-changed', self.save_setting, \
'line-thickness', self.pref_thickness_scale.get_value)
# `notify::state` signal returns additional parameter that
From c5755d869071bb1c9767d26c412fe933c2d7a861 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Fri, 3 Feb 2023 12:10:29 +0300
Subject: [PATCH 13/19] Fix particles mode
It was broken after previous commit
---
src/draw_functions.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index b8f1b0a..9523c78 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -162,8 +162,8 @@ def levels(sample, cr, width, height, colors, offset, radius, fill, thickness):
for i in range(ls):
q = int(round(sample[i], 1) * 10)
for r in range(q):
- draw_element(cr, step * i + offset_px + thickness / 2, \
- height - (height / 10 * (r + 1)) + offset_px / 2 + thickness / 2, \
+ draw_element(cr, step * (i + 0.5), \
+ height - (height / 10 * (r + 0.5)), \
max(step - offset_px * 2 - thickness, 1), \
max(height / 10 - offset_px - thickness, 1), radius)
cr.fill() if fill else cr.stroke()
From 6c93e4a4d8a9e2521ced2b5fb0178b7302042181 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Sun, 5 Feb 2023 02:11:41 +0300
Subject: [PATCH 14/19] Remove bars-fill setting and use fill instead
---
data/io.github.fsobolev.Cavalier.gschema.xml | 10 ----------
src/draw_functions.py | 5 +----
src/drawing_area.py | 3 +--
src/preferences_window.py | 11 -----------
4 files changed, 2 insertions(+), 27 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 3d4786d..70b79e0 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -37,16 +37,6 @@
"wave"
-
- Bars Filling
- Filling rule for Bars drawing mode
-
-
-
-
-
- "bars"
-
Circle
Whether to modify drawing modes to draw in circle
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 9523c78..9cba529 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -269,7 +269,4 @@ def bars_circle(sample, cr, width, height, colors, offset, fill, thickness, \
height / 2 + math.sin(2 * math.pi / ls * \
(i + 1 - offset / 100) - 0.5 * math.pi) * min_radius)
cr.close_path()
- if fill == "all":
- cr.move_to(width / 2 + min_radius, height / 2)
- cr.arc(width / 2, height / 2, min_radius, 0, 2 * math.pi)
- cr.stroke() if fill == "outline" else cr.fill()
+ cr.fill() if fill else cr.stroke()
diff --git a/src/drawing_area.py b/src/drawing_area.py
index 266a7b7..0aee719 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -64,7 +64,6 @@ def run(self):
def on_settings_changed(self, key):
self.draw_mode = self.settings['mode']
- self.bars_fill = self.settings['bars-fill']
self.circle = self.settings['circle']
self.wave_circle_fill = self.settings['wave-circle-fill']
self.radius = self.settings['radius']
@@ -121,7 +120,7 @@ def draw_func(self, area, cr, width, height, data, n):
elif self.draw_mode == 'bars':
if self.circle:
bars_circle(self.cava_sample, cr, width, height, \
- self.colors, self.offset, self.bars_fill, \
+ self.colors, self.offset, self.fill, \
self.thickness, self.radius)
else:
bars(self.cava_sample, cr, width, height, self.colors, \
diff --git a/src/preferences_window.py b/src/preferences_window.py
index 4af5424..18e61b2 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -105,10 +105,6 @@ def create_cavalier_page(self):
self.bars_check_btn.set_group(self.wave_check_btn)
self.bars_row.add_prefix(self.bars_check_btn)
self.bars_row.set_activatable_widget(self.bars_check_btn)
- self.bars_fill_dropdown = Gtk.DropDown.new_from_strings( \
- [_('Outline'), _('Fill bars'), _('Fill bars and circle')])
- self.bars_fill_dropdown.set_valign(Gtk.Align.CENTER)
- self.bars_row.add_suffix(self.bars_fill_dropdown)
self.cavalier_mode_group.add(self.bars_row)
self.mode_variant_stack = Gtk.Stack.new()
@@ -451,9 +447,6 @@ def load_settings(self):
self.particles_check_btn, self.spine_check_btn, self.bars_check_btn)[ \
self.settings.get_range('mode')[1].index(self.settings['mode']) \
].set_active(True)
- self.bars_fill_dropdown.set_selected( \
- self.settings.get_range('bars-fill')[1].index( \
- self.settings['bars-fill']))
self.mode_variant_stack.set_visible_child_name( \
'circle' if self.settings['circle'] else 'box')
self.wave_circle_fill_box.set_visible(self.settings['circle'])
@@ -521,10 +514,6 @@ def bind_settings(self):
'particles')
self.spine_check_btn.connect('toggled', self.change_mode, 'spine')
self.bars_check_btn.connect('toggled', self.change_mode, 'bars')
- self.bars_fill_dropdown.connect('notify::selected-item', \
- lambda *args: self.save_setting(self.bars_fill_dropdown, \
- 'bars-fill', self.settings.get_range('bars-fill')[1][ \
- self.bars_fill_dropdown.get_selected()]))
# `notify::visible-child` signal returns additional parameter that
# we don't need, that's why lambda is used.
self.mode_variant_stack.connect('notify::visible-child', \
From 44ed2b746a149df9b5ac7b5e3e74319218f8e2d5 Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Sun, 5 Feb 2023 05:46:09 +0300
Subject: [PATCH 15/19] Make Bars Circle mode more or less working
---
src/draw_functions.py | 86 +++++++++++++++++++++++++++++--------------
1 file changed, 59 insertions(+), 27 deletions(-)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 9cba529..dfa86d6 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -240,33 +240,65 @@ def bars_circle(sample, cr, width, height, colors, offset, fill, thickness, \
min_radius = min(width, height) * radius / 400
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, max_radius, colors)
- cr.set_line_width(thickness)
+ if fill:
+ thickness = 0
+ thickness_inner_angle = 0
+ else:
+ thickness = min(thickness, \
+ min_radius * math.pi * 2 / ls * 0.25)
+ cr.set_line_width(thickness)
+ thickness_inner_angle = math.asin(math.sin(0.25 * math.pi) / \
+ math.sqrt(min_radius ** 2 + (thickness / 2) ** 2 - 2 * \
+ min_radius * thickness / 2 * math.cos(0.25 * math.pi)) * \
+ thickness / 2)
for i in range(ls):
- cr.move_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + offset / 100) - 0.5 * math.pi) * min_radius, \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + offset / 100) - 0.5 * math.pi) * min_radius)
- cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + offset / 100) - 0.5 * math.pi) * \
- (min_radius + sample[i] * (max_radius - min_radius)), \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + offset / 100) - 0.5 * math.pi) * \
- (min_radius + sample[i] * (max_radius - min_radius)))
- cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * \
- (min_radius + sample[i] * (max_radius - min_radius)), \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * \
- (min_radius + sample[i] * (max_radius - min_radius)))
- cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * \
- (min_radius + sample[i] * (max_radius - min_radius)), \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * \
- (min_radius + sample[i] * (max_radius - min_radius)))
- cr.line_to(width / 2 + math.cos(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius, \
- height / 2 + math.sin(2 * math.pi / ls * \
- (i + 1 - offset / 100) - 0.5 * math.pi) * min_radius)
+ cr.move_to(width / 2 + math.cos( \
+ 2 * math.pi / ls * (i + offset / 100) - 0.5 * math.pi + \
+ thickness_inner_angle) * (min_radius + thickness / 2),
+ height / 2 + math.sin( \
+ 2 * math.pi / ls * (i + offset / 100) - 0.5 * math.pi + \
+ thickness_inner_angle) * (min_radius + thickness / 2))
+ cr.line_to(width / 2 + math.cos( \
+ 2 * math.pi / ls * (i + offset / 100) - 0.5 * math.pi + \
+ math.asin(math.sin(0.25 * math.pi) / math.sqrt((min_radius + \
+ max(sample[i] * (max_radius - min_radius), thickness * 2)) ** 2 + \
+ (thickness / 2) ** 2 - 2 * (min_radius + sample[i] * \
+ (max_radius - min_radius)) * thickness / 2 * \
+ math.cos(0.25 * math.pi)) * thickness / 2)) * \
+ (min_radius + max(sample[i] * \
+ (max_radius - min_radius), thickness * 2) - thickness / 2), \
+ height / 2 + math.sin( \
+ 2 * math.pi / ls * (i + offset / 100) - 0.5 * math.pi + \
+ math.asin(math.sin(0.25 * math.pi) / math.sqrt((min_radius + \
+ max(sample[i] * (max_radius - min_radius), thickness * 2)) ** 2 + \
+ (thickness / 2) ** 2 - 2 * (min_radius + sample[i] * \
+ (max_radius - min_radius)) * thickness / 2 * \
+ math.cos(0.25 * math.pi)) * thickness / 2)) * \
+ (min_radius + max(sample[i] * \
+ (max_radius - min_radius), thickness * 2) - thickness / 2))
+ cr.line_to(width / 2 + math.cos( \
+ 2 * math.pi / ls * (i + 1 - offset / 100) - 0.5 * math.pi - \
+ math.asin(math.sin(0.25 * math.pi) / math.sqrt((min_radius + \
+ max(sample[i] * (max_radius - min_radius), thickness * 2)) ** 2 + \
+ (thickness / 2) ** 2 - 2 * (min_radius + max(sample[i] * \
+ (max_radius - min_radius), thickness * 2)) * thickness / 2 * \
+ math.cos(0.25 * math.pi)) * thickness / 2)) * \
+ (min_radius + max(sample[i] * \
+ (max_radius - min_radius), thickness * 2) - thickness / 2), \
+ height / 2 + math.sin( \
+ 2 * math.pi / ls * (i + 1 - offset / 100) - 0.5 * math.pi - \
+ math.asin(math.sin(0.25 * math.pi) / math.sqrt((min_radius + \
+ max(sample[i] * (max_radius - min_radius), thickness * 2)) ** 2 + \
+ (thickness / 2) ** 2 - 2 * (min_radius + max(sample[i] * \
+ (max_radius - min_radius), thickness * 2)) * thickness / 2 * \
+ math.cos(0.25 * math.pi)) * thickness / 2)) * \
+ (min_radius + max(sample[i] * \
+ (max_radius - min_radius), thickness * 2) - thickness / 2))
+ cr.line_to(width / 2 + math.cos( \
+ 2 * math.pi / ls * (i + 1 - offset / 100) - 0.5 * math.pi - \
+ thickness_inner_angle) * (min_radius + thickness / 2), \
+ height / 2 + math.sin( \
+ 2 * math.pi / ls * (i + 1 - offset / 100) - 0.5 * math.pi - \
+ thickness_inner_angle) * (min_radius + thickness / 2))
cr.close_path()
cr.fill() if fill else cr.stroke()
From 4abee931aa95b601a62ebdacc02fcedd2657fe0b Mon Sep 17 00:00:00 2001
From: Fyodor Sobolev <117388856+fsobolev@users.noreply.github.com>
Date: Sun, 5 Feb 2023 06:12:50 +0300
Subject: [PATCH 16/19] Improve box/circle preferences
---
src/preferences_window.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/preferences_window.py b/src/preferences_window.py
index 18e61b2..7a92e83 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -113,8 +113,9 @@ def create_cavalier_page(self):
self.box_group = Adw.PreferencesGroup.new()
self.mode_variant_stack.add_titled(self.box_group, 'box', _('Box'))
- self.mirror_row = Adw.ActionRow.new()
- self.mirror_row.set_title(_('Mirror'))
+ self.pref_mirror = Adw.ActionRow.new()
+ self.pref_mirror.set_title(_('Mirror'))
+ self.box_group.add(self.pref_mirror)
self.circle_group = Adw.PreferencesGroup.new()
self.mode_variant_stack.add_titled(self.circle_group, 'circle', \
@@ -449,6 +450,8 @@ def load_settings(self):
].set_active(True)
self.mode_variant_stack.set_visible_child_name( \
'circle' if self.settings['circle'] else 'box')
+ self.box_group.set_visible(not self.settings['circle'])
+ self.circle_group.set_visible(self.settings['circle'])
self.wave_circle_fill_box.set_visible(self.settings['circle'])
self.wave_circle_fill_switch.set_active( \
self.settings['wave-circle-fill'])
From e35fe1a9cf22198e18f853f38f92c1f424e24724 Mon Sep 17 00:00:00 2001
From: gregorni <119804311+gregorni@users.noreply.github.com>
Date: Sun, 5 Feb 2023 12:30:45 +0100
Subject: [PATCH 17/19] add line circle mode to wave circle mode
---
src/draw_functions.py | 7 ++++---
src/drawing_area.py | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/draw_functions.py b/src/draw_functions.py
index dfa86d6..da34a09 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -91,14 +91,14 @@ def wave(sample, cr, width, height, colors, fill, thickness):
cr.set_line_width(thickness)
cr.stroke()
-def wave_circle(sample, cr, width, height, colors, radius, thickness, fill):
+def wave_circle(sample, cr, width, height, colors, radius, fill, thickness, fill_middle):
ls = len(sample)
cr.move_to(width / 2, height / 2)
min_radius = min(width, height) * radius / 400
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, \
max_radius, colors)
- if not fill:
+ if not fill_middle:
cr.rectangle(0, 0, width, height)
cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, \
2 * math.pi, 0)
@@ -145,7 +145,8 @@ def wave_circle(sample, cr, width, height, colors, radius, thickness, fill):
(min_radius + sample[i+1] * (max_radius - min_radius))
)
cr.close_path() # required to avoid artifact with thick lines
- cr.fill()
+ cr.set_line_width(thickness)
+ cr.fill() if fill else cr.stroke()
def levels(sample, cr, width, height, colors, offset, radius, fill, thickness):
set_source(cr, height, colors)
diff --git a/src/drawing_area.py b/src/drawing_area.py
index 0aee719..b0f64dc 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -103,7 +103,7 @@ def draw_func(self, area, cr, width, height, data, n):
if self.draw_mode == 'wave':
if self.circle:
wave_circle(self.cava_sample, cr, width, height, \
- self.colors, self.radius, self.thickness, \
+ self.colors, self.radius, self.fill, self.thickness, \
self.wave_circle_fill)
else:
wave(self.cava_sample, cr, width, height, self.colors, \
From bef1f13970c32d1a3f2f008605c90d27fabd4aae Mon Sep 17 00:00:00 2001
From: gregorni <119804311+gregorni@users.noreply.github.com>
Date: Sun, 5 Feb 2023 12:52:10 +0100
Subject: [PATCH 18/19] improve & rename Wave mode fill circle setting
---
data/io.github.fsobolev.Cavalier.gschema.xml | 4 ++--
src/draw_functions.py | 4 ++--
src/preferences_window.py | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 70b79e0..439a064 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -43,8 +43,8 @@
false
- Wave - Fill Circle
- Whether to fill the inner circle when using Wave mode Circle variant.
+ Wave - Show Inner Circle
+ Whether to show the inner circle when using Wave mode Circle variant.
false
diff --git a/src/draw_functions.py b/src/draw_functions.py
index da34a09..9a42d57 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -91,14 +91,14 @@ def wave(sample, cr, width, height, colors, fill, thickness):
cr.set_line_width(thickness)
cr.stroke()
-def wave_circle(sample, cr, width, height, colors, radius, fill, thickness, fill_middle):
+def wave_circle(sample, cr, width, height, colors, radius, fill, thickness, show_inner_circle):
ls = len(sample)
cr.move_to(width / 2, height / 2)
min_radius = min(width, height) * radius / 400
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, \
max_radius, colors)
- if not fill_middle:
+ if show_inner_circle:
cr.rectangle(0, 0, width, height)
cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, \
2 * math.pi, 0)
diff --git a/src/preferences_window.py b/src/preferences_window.py
index 7a92e83..9a95968 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -68,7 +68,7 @@ def create_cavalier_page(self):
self.wave_row.set_activatable_widget(self.wave_check_btn)
self.wave_circle_fill_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10)
self.wave_row.add_suffix(self.wave_circle_fill_box)
- self.wave_circle_fill_label = Gtk.Label.new(_('Fill completely'))
+ self.wave_circle_fill_label = Gtk.Label.new(_('Show inner circle'))
self.wave_circle_fill_box.append(self.wave_circle_fill_label)
self.wave_circle_fill_switch = Gtk.Switch.new()
self.wave_circle_fill_switch.set_valign(Gtk.Align.CENTER)
From ce18fead1c0f8c76adbb221da1f855e1ead5fc8a Mon Sep 17 00:00:00 2001
From: gregorni <119804311+gregorni@users.noreply.github.com>
Date: Sun, 5 Feb 2023 13:18:26 +0100
Subject: [PATCH 19/19] Add shortcut for inner circle & more renaming
---
data/io.github.fsobolev.Cavalier.gschema.xml | 2 +-
src/draw_functions.py | 4 +--
src/drawing_area.py | 4 +--
src/preferences_window.py | 26 ++++++++++----------
src/shortcuts.py | 7 ++++++
src/shortcuts_dialog.ui | 6 +++++
6 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/data/io.github.fsobolev.Cavalier.gschema.xml b/data/io.github.fsobolev.Cavalier.gschema.xml
index 439a064..0330015 100644
--- a/data/io.github.fsobolev.Cavalier.gschema.xml
+++ b/data/io.github.fsobolev.Cavalier.gschema.xml
@@ -42,7 +42,7 @@
Whether to modify drawing modes to draw in circle
false
-
+
Wave - Show Inner Circle
Whether to show the inner circle when using Wave mode Circle variant.
false
diff --git a/src/draw_functions.py b/src/draw_functions.py
index 9a42d57..e4cc1e8 100644
--- a/src/draw_functions.py
+++ b/src/draw_functions.py
@@ -91,14 +91,14 @@ def wave(sample, cr, width, height, colors, fill, thickness):
cr.set_line_width(thickness)
cr.stroke()
-def wave_circle(sample, cr, width, height, colors, radius, fill, thickness, show_inner_circle):
+def wave_circle(sample, cr, width, height, colors, radius, fill, thickness, inner_circle):
ls = len(sample)
cr.move_to(width / 2, height / 2)
min_radius = min(width, height) * radius / 400
max_radius = min(width, height) / 2
set_source_radial(cr, width / 2, height / 2, min_radius, \
max_radius, colors)
- if show_inner_circle:
+ if inner_circle:
cr.rectangle(0, 0, width, height)
cr.arc_negative(width / 2, height / 2, min_radius - thickness / 2, \
2 * math.pi, 0)
diff --git a/src/drawing_area.py b/src/drawing_area.py
index b0f64dc..7a80712 100644
--- a/src/drawing_area.py
+++ b/src/drawing_area.py
@@ -65,7 +65,7 @@ def run(self):
def on_settings_changed(self, key):
self.draw_mode = self.settings['mode']
self.circle = self.settings['circle']
- self.wave_circle_fill = self.settings['wave-circle-fill']
+ self.wave_inner_circle = self.settings['wave-inner-circle']
self.radius = self.settings['radius']
self.set_margin_top(self.settings['margin'])
self.set_margin_bottom(self.settings['margin'])
@@ -104,7 +104,7 @@ def draw_func(self, area, cr, width, height, data, n):
if self.circle:
wave_circle(self.cava_sample, cr, width, height, \
self.colors, self.radius, self.fill, self.thickness, \
- self.wave_circle_fill)
+ self.wave_inner_circle)
else:
wave(self.cava_sample, cr, width, height, self.colors, \
self.fill, self.thickness)
diff --git a/src/preferences_window.py b/src/preferences_window.py
index 9a95968..572030c 100644
--- a/src/preferences_window.py
+++ b/src/preferences_window.py
@@ -66,13 +66,13 @@ def create_cavalier_page(self):
self.wave_check_btn = Gtk.CheckButton.new()
self.wave_row.add_prefix(self.wave_check_btn)
self.wave_row.set_activatable_widget(self.wave_check_btn)
- self.wave_circle_fill_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10)
- self.wave_row.add_suffix(self.wave_circle_fill_box)
- self.wave_circle_fill_label = Gtk.Label.new(_('Show inner circle'))
- self.wave_circle_fill_box.append(self.wave_circle_fill_label)
- self.wave_circle_fill_switch = Gtk.Switch.new()
- self.wave_circle_fill_switch.set_valign(Gtk.Align.CENTER)
- self.wave_circle_fill_box.append(self.wave_circle_fill_switch)
+ self.wave_inner_circle_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10)
+ self.wave_row.add_suffix(self.wave_inner_circle_box)
+ self.wave_inner_circle_label = Gtk.Label.new(_('Show inner circle'))
+ self.wave_inner_circle_box.append(self.wave_inner_circle_label)
+ self.wave_inner_circle_switch = Gtk.Switch.new()
+ self.wave_inner_circle_switch.set_valign(Gtk.Align.CENTER)
+ self.wave_inner_circle_box.append(self.wave_inner_circle_switch)
self.cavalier_mode_group.add(self.wave_row)
self.levels_row = Adw.ActionRow.new()
@@ -452,9 +452,9 @@ def load_settings(self):
'circle' if self.settings['circle'] else 'box')
self.box_group.set_visible(not self.settings['circle'])
self.circle_group.set_visible(self.settings['circle'])
- self.wave_circle_fill_box.set_visible(self.settings['circle'])
- self.wave_circle_fill_switch.set_active( \
- self.settings['wave-circle-fill'])
+ self.wave_inner_circle_box.set_visible(self.settings['circle'])
+ self.wave_inner_circle_switch.set_active( \
+ self.settings['wave-inner-circle'])
self.pref_radius_scale.set_value(self.settings['radius'])
self.pref_margin_scale.set_value(self.settings['margin'])
self.pref_offset_scale.set_value(self.settings['items-offset'])
@@ -509,9 +509,9 @@ def load_settings(self):
def bind_settings(self):
self.wave_check_btn.connect('toggled', self.change_mode, 'wave')
- self.wave_circle_fill_switch.connect('notify::state', \
- lambda *args : self.save_setting(self.wave_circle_fill_switch, \
- 'wave-circle-fill', self.wave_circle_fill_switch.get_state()))
+ self.wave_inner_circle_switch.connect('notify::state', \
+ lambda *args : self.save_setting(self.wave_inner_circle_switch, \
+ 'wave-inner-circle', self.wave_inner_circle_switch.get_state()))
self.levels_check_btn.connect('toggled', self.change_mode, 'levels')
self.particles_check_btn.connect('toggled', self.change_mode, \
'particles')
diff --git a/src/shortcuts.py b/src/shortcuts.py
index 411d8e9..b864890 100644
--- a/src/shortcuts.py
+++ b/src/shortcuts.py
@@ -110,6 +110,13 @@ def add_shortcuts(widget, settings):
Gtk.ShortcutTrigger.parse_string("T"), \
Gtk.NamedAction.new("cavalier.decrease-thickness")))
+ act_toggle_inner_circle = Gio.SimpleAction.new("toggle-inner-circle", None)
+ act_toggle_inner_circle.connect('activate', toggle_setting, settings, 'wave-inner-circle')
+ action_map.add_action(act_toggle_inner_circle)
+ shortcut_controller.add_shortcut(Gtk.Shortcut.new( \
+ Gtk.ShortcutTrigger.parse_string("I"), \
+ Gtk.NamedAction.new("cavalier.toggle-inner-circle")))
+
act_toggle_fill = Gio.SimpleAction.new("toggle-fill", None)
act_toggle_fill.connect('activate', toggle_setting, settings, 'fill')
action_map.add_action(act_toggle_fill)
diff --git a/src/shortcuts_dialog.ui b/src/shortcuts_dialog.ui
index 68a4771..a6cd627 100644
--- a/src/shortcuts_dialog.ui
+++ b/src/shortcuts_dialog.ui
@@ -34,6 +34,12 @@
R <Shift>R
+
+
+