From cec918728bb18cb8c7d79fec7b9b4cb5d9d120d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 18 Aug 2026 19:30:16 -0700 Subject: [PATCH 1/4] Granite.Symbol: improve API --- data/icons/bluetooth.svg | 12 +++++----- src/Widgets/DisplayWidget.vala | 6 ++--- src/Widgets/Symbol.vala | 43 ++++++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/data/icons/bluetooth.svg b/data/icons/bluetooth.svg index 17fc9c31..9002fde1 100644 --- a/data/icons/bluetooth.svg +++ b/data/icons/bluetooth.svg @@ -3,7 +3,7 @@ xmlns:svg='http://www.w3.org/2000/svg' xmlns:gpa='https://www.gtk.org/grappa' gpa:version='1' - gpa:state-names='state0 state1 state2' + gpa:state-names='normal disabled checked' gpa:state='0' id='svg6' width='24' @@ -18,7 +18,7 @@ fill-rule='nonzero' overflow='visible' d='M 11.5 5 C 11.223 5, 11 5.223, 11 5.5 L 11 10.375 L 9.281 8.875 C 8.968 8.602, 8.523 8.655, 8.251 8.969 A 0.753 0.753 0 0 0 8.313 10.031 L 10.563 12 L 8.313 13.969 A 0.753 0.753 0 0 0 8.25 15.031 C 8.523 15.344, 8.968 15.398, 9.281 15.125 L 11.001 13.625 L 11.001 18.5 C 11.001 18.777, 11.223 19, 11.501 19 C 11.783 19, 11.938 18.98, 12.156 18.812 L 15.688 15.656 A 0.78 0.78 0 0 0 15.906 15.281 A 0.745 0.745 0 0 0 15.938 15 A 0.723 0.723 0 0 0 15.906 14.844 A 0.78 0.78 0 0 0 15.688 14.469 L 12.875 11.999 L 15.688 9.531 A 0.78 0.78 0 0 0 15.906 9.156 A 0.71 0.71 0 0 0 15.906 8.719 A 0.78 0.78 0 0 0 15.688 8.344 L 12.156 5.187 C 11.957 5.027, 11.729 5, 11.5 5 Z M 12 7.063 L 14.094 8.938 L 12 10.75 Z M 12 13.25 L 14.094 15.063 L 12 16.938 Z' - gpa:states='state0 state1 state2' + gpa:states='normal disabled checked' gpa:animation-repeat='0' gpa:animation-segment='0'> @@ -39,7 +39,7 @@ y2='18.6085' gpa:stroke-minwidth='25%' gpa:stroke-maxwidth='200%' - gpa:states='state1' + gpa:states='disabled' gpa:transition-type='animate' gpa:transition-easing='ease-in-out' gpa:transition-duration='200ms'> @@ -52,7 +52,7 @@ fill-opacity='0.5' fill-rule='nonzero' d='M 6.31836 5 C 6.04055 5.00054, 5.78575 5.15461, 5.65625 5.40039 L 5.6543 5.40039 C 4.56857 7.43076, 4.00036 9.69757, 4 12 C 4.00035 14.3024, 4.56859 16.5692, 5.6543 18.5996 L 5.65625 18.5996 C 5.78576 18.8454, 6.04053 18.9995, 6.31836 19 C 6.73257 19, 7.06836 18.6642, 7.06836 18.25 C 7.068 18.1251, 7.03645 18.0022, 6.97656 17.8926 C 6.00732 16.0797, 5.50016 14.0557, 5.5 12 C 5.50016 9.94428, 6.00733 7.92031, 6.97656 6.10742 C 7.03645 5.99779, 7.068 5.87493, 7.06836 5.75 C 7.06836 5.33579, 6.73257 5, 6.31836 5 Z M 17.6816 5 C 17.2674 5, 16.9316 5.33579, 16.9316 5.75 C 16.932 5.87493, 16.9636 5.99779, 17.0234 6.10742 C 17.9927 7.92031, 18.4998 9.94428, 18.5 12 C 18.4998 14.0557, 17.9927 16.0797, 17.0234 17.8926 C 16.9635 18.0022, 16.932 18.1251, 16.9316 18.25 C 16.9316 18.6642, 17.2674 19, 17.6816 19 C 17.9595 18.9995, 18.2142 18.8454, 18.3437 18.5996 L 18.3457 18.5996 C 19.4314 16.5692, 19.9997 14.3024, 20 12 C 19.9996 9.69757, 19.4314 7.43076, 18.3457 5.40039 L 18.3437 5.40039 C 18.2143 5.15461, 17.9594 5.00054, 17.6816 5 Z' - gpa:states='state2' + gpa:states='checked' gpa:transition-type='fade' gpa:transition-easing='ease-in-out' gpa:transition-duration='200ms' @@ -88,7 +88,7 @@ y2='20.23' gpa:stroke-minwidth='25%' gpa:stroke-maxwidth='200%' - gpa:states='state1' + gpa:states='disabled' gpa:transition-type='animate' gpa:transition-easing='ease-in-out' gpa:transition-duration='200ms'> @@ -113,7 +113,7 @@ ry='1' gpa:stroke-minwidth='25%' gpa:stroke-maxwidth='150%' - gpa:states='state1' + gpa:states='disabled' gpa:transition-type='fade' gpa:transition-easing='ease-in-out' gpa:transition-duration='200ms'> diff --git a/src/Widgets/DisplayWidget.vala b/src/Widgets/DisplayWidget.vala index b14ede6e..7b730bd5 100644 --- a/src/Widgets/DisplayWidget.vala +++ b/src/Widgets/DisplayWidget.vala @@ -60,14 +60,14 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Granite.Bin { if (state) { context = _("Middle-click to turn Bluetooth off"); if (connected) { - symbol.state = Granite.Symbol.STATE_CHECKED; + symbol.state = Granite.Symbol.State.CHECKED; description = _("Bluetooth connected"); } else { - symbol.state = Granite.Symbol.STATE_NORMAL; + symbol.state = Granite.Symbol.State.NORMAL; description = _("Bluetooth is on"); } } else { - symbol.state = Granite.Symbol.STATE_DISABLED; + symbol.state = Granite.Symbol.State.DISABLED; description = _("Bluetooth is off"); context = _("Middle-click to turn Bluetooth on"); } diff --git a/src/Widgets/Symbol.vala b/src/Widgets/Symbol.vala index 30b0d624..885a3118 100644 --- a/src/Widgets/Symbol.vala +++ b/src/Widgets/Symbol.vala @@ -4,9 +4,11 @@ */ public class Granite.Symbol : Granite.Bin { - public const int STATE_NORMAL = 0; - public const int STATE_DISABLED = 1; - public const int STATE_CHECKED = 2; + public interface State { + public const string NORMAL = "normal"; + public const string DISABLED = "disabled"; + public const string CHECKED = "checked"; + } public string resource_path { get; construct; } @@ -15,9 +17,40 @@ public class Granite.Symbol : Granite.Bin { set { image.pixel_size = value; } } - public uint state { + public uint state_index { get { return svg.state; } - set { svg.state = value; } + set { + uint length = -1; + svg.get_state_names (out length); + + if (value > length - 1) { + warning ("Granite.Symbol set to undefined state. Ignoring."); + return; + } + + svg.state = value; + notify_property ("state"); + } + } + + public string state { + get { + uint length = -1; + return svg.get_state_names (out length)[state_index]; + } + set { + uint length = -1; + var names = svg.get_state_names (out length); + + for (int i = 0; i < length; i++) { + if (names[i] == value) { + state_index = i; + return; + } + } + + warning ("Granite.Symbol set to undefined state. Ignoring."); + } } private Gtk.Image image; From 042459b195cf4a1555a8402dcd919bbb537bd70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 18 Aug 2026 19:37:11 -0700 Subject: [PATCH 2/4] Seal those constants --- src/Widgets/Symbol.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Widgets/Symbol.vala b/src/Widgets/Symbol.vala index 885a3118..3a8d4cc3 100644 --- a/src/Widgets/Symbol.vala +++ b/src/Widgets/Symbol.vala @@ -4,7 +4,7 @@ */ public class Granite.Symbol : Granite.Bin { - public interface State { + public sealed interface State { public const string NORMAL = "normal"; public const string DISABLED = "disabled"; public const string CHECKED = "checked"; From 345194ed10cedce84c0fcd7118d1e8f46c902593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 18 Aug 2026 19:42:52 -0700 Subject: [PATCH 3/4] minor comments --- src/Widgets/Symbol.vala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Widgets/Symbol.vala b/src/Widgets/Symbol.vala index 3a8d4cc3..9a6fa1e0 100644 --- a/src/Widgets/Symbol.vala +++ b/src/Widgets/Symbol.vala @@ -5,7 +5,9 @@ public class Granite.Symbol : Granite.Bin { public sealed interface State { + // The default state public const string NORMAL = "normal"; + // Disabled state represented by a slash public const string DISABLED = "disabled"; public const string CHECKED = "checked"; } From c371512d66b4cc4cadce360cb5eec468971e2615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 19 Aug 2026 09:31:37 -0700 Subject: [PATCH 4/4] Constants in a namespace --- data/icons/bluetooth.svg | 6 +++--- src/Widgets/DisplayWidget.vala | 6 +++--- src/Widgets/Symbol.vala | 17 +++++++++-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/data/icons/bluetooth.svg b/data/icons/bluetooth.svg index 9002fde1..e9932cdf 100644 --- a/data/icons/bluetooth.svg +++ b/data/icons/bluetooth.svg @@ -3,7 +3,7 @@ xmlns:svg='http://www.w3.org/2000/svg' xmlns:gpa='https://www.gtk.org/grappa' gpa:version='1' - gpa:state-names='normal disabled checked' + gpa:state-names='normal disabled active' gpa:state='0' id='svg6' width='24' @@ -18,7 +18,7 @@ fill-rule='nonzero' overflow='visible' d='M 11.5 5 C 11.223 5, 11 5.223, 11 5.5 L 11 10.375 L 9.281 8.875 C 8.968 8.602, 8.523 8.655, 8.251 8.969 A 0.753 0.753 0 0 0 8.313 10.031 L 10.563 12 L 8.313 13.969 A 0.753 0.753 0 0 0 8.25 15.031 C 8.523 15.344, 8.968 15.398, 9.281 15.125 L 11.001 13.625 L 11.001 18.5 C 11.001 18.777, 11.223 19, 11.501 19 C 11.783 19, 11.938 18.98, 12.156 18.812 L 15.688 15.656 A 0.78 0.78 0 0 0 15.906 15.281 A 0.745 0.745 0 0 0 15.938 15 A 0.723 0.723 0 0 0 15.906 14.844 A 0.78 0.78 0 0 0 15.688 14.469 L 12.875 11.999 L 15.688 9.531 A 0.78 0.78 0 0 0 15.906 9.156 A 0.71 0.71 0 0 0 15.906 8.719 A 0.78 0.78 0 0 0 15.688 8.344 L 12.156 5.187 C 11.957 5.027, 11.729 5, 11.5 5 Z M 12 7.063 L 14.094 8.938 L 12 10.75 Z M 12 13.25 L 14.094 15.063 L 12 16.938 Z' - gpa:states='normal disabled checked' + gpa:states='normal disabled active' gpa:animation-repeat='0' gpa:animation-segment='0'> @@ -52,7 +52,7 @@ fill-opacity='0.5' fill-rule='nonzero' d='M 6.31836 5 C 6.04055 5.00054, 5.78575 5.15461, 5.65625 5.40039 L 5.6543 5.40039 C 4.56857 7.43076, 4.00036 9.69757, 4 12 C 4.00035 14.3024, 4.56859 16.5692, 5.6543 18.5996 L 5.65625 18.5996 C 5.78576 18.8454, 6.04053 18.9995, 6.31836 19 C 6.73257 19, 7.06836 18.6642, 7.06836 18.25 C 7.068 18.1251, 7.03645 18.0022, 6.97656 17.8926 C 6.00732 16.0797, 5.50016 14.0557, 5.5 12 C 5.50016 9.94428, 6.00733 7.92031, 6.97656 6.10742 C 7.03645 5.99779, 7.068 5.87493, 7.06836 5.75 C 7.06836 5.33579, 6.73257 5, 6.31836 5 Z M 17.6816 5 C 17.2674 5, 16.9316 5.33579, 16.9316 5.75 C 16.932 5.87493, 16.9636 5.99779, 17.0234 6.10742 C 17.9927 7.92031, 18.4998 9.94428, 18.5 12 C 18.4998 14.0557, 17.9927 16.0797, 17.0234 17.8926 C 16.9635 18.0022, 16.932 18.1251, 16.9316 18.25 C 16.9316 18.6642, 17.2674 19, 17.6816 19 C 17.9595 18.9995, 18.2142 18.8454, 18.3437 18.5996 L 18.3457 18.5996 C 19.4314 16.5692, 19.9997 14.3024, 20 12 C 19.9996 9.69757, 19.4314 7.43076, 18.3457 5.40039 L 18.3437 5.40039 C 18.2143 5.15461, 17.9594 5.00054, 17.6816 5 Z' - gpa:states='checked' + gpa:states='active' gpa:transition-type='fade' gpa:transition-easing='ease-in-out' gpa:transition-duration='200ms' diff --git a/src/Widgets/DisplayWidget.vala b/src/Widgets/DisplayWidget.vala index 7b730bd5..a61f585a 100644 --- a/src/Widgets/DisplayWidget.vala +++ b/src/Widgets/DisplayWidget.vala @@ -60,14 +60,14 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Granite.Bin { if (state) { context = _("Middle-click to turn Bluetooth off"); if (connected) { - symbol.state = Granite.Symbol.State.CHECKED; + symbol.state = Granite.SymbolState.ACTIVE; description = _("Bluetooth connected"); } else { - symbol.state = Granite.Symbol.State.NORMAL; + symbol.state = Granite.SymbolState.NORMAL; description = _("Bluetooth is on"); } } else { - symbol.state = Granite.Symbol.State.DISABLED; + symbol.state = Granite.SymbolState.DISABLED; description = _("Bluetooth is off"); context = _("Middle-click to turn Bluetooth on"); } diff --git a/src/Widgets/Symbol.vala b/src/Widgets/Symbol.vala index 9a6fa1e0..dbc77b5e 100644 --- a/src/Widgets/Symbol.vala +++ b/src/Widgets/Symbol.vala @@ -3,15 +3,16 @@ * SPDX-FileCopyrightText: 2026 elementary, Inc. (https://elementary.io) */ -public class Granite.Symbol : Granite.Bin { - public sealed interface State { - // The default state - public const string NORMAL = "normal"; - // Disabled state represented by a slash - public const string DISABLED = "disabled"; - public const string CHECKED = "checked"; - } +namespace Granite.SymbolState { + // The default state + public const string NORMAL = "normal"; + // Disabled state represented by a slash + public const string DISABLED = "disabled"; + // e.g. paired, connected, needs attention + public const string ACTIVE = "active"; +} +public class Granite.Symbol : Granite.Bin { public string resource_path { get; construct; } public int pixel_size {