Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add slider widget #435

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion man/swaync.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ config file to be able to detect config errors
type: bool ++
default: true ++
description: Display notification timestamps relative to now e.g. \"26 minutes ago\". ++
If false, a local iso8601-formatted absolute timestamp is displayed.
If false, a local iso8601-formatted absolute timestamp is displayed.

*control-center-height* ++
type: integer ++
Expand Down Expand Up @@ -231,6 +231,8 @@ config file to be able to detect config errors
optional: true ++
*buttons-grid*++
optional: true ++
*slider*++
optional: true ++
#START pulse-audio
*volume*++
optional: true ++
Expand Down Expand Up @@ -470,6 +472,51 @@ config file to be able to detect config errors
description: Wether the toggle button is active as default or not ++
description: A list of actions containing a label and a command ++
description: A grid of buttons that execute shell commands ++
*slider*++
type: object ++
css class: widget-slider ++
properties: ++
label: ++
type: string ++
optional: true ++
default: "slider" ++
description: Text displayed in front of the slider ++
cmd_setter: ++
type: string ++
optional: true ++
default: "" ++
description: command to set the value ++
cmd_getter: ++
type: string ++
optional: true ++
default: "" ++
description: command to get the actual value ++
min: ++
type: integer ++
optional: true ++
default: 0 ++
description: minimum value of the slider range ++
max: ++
type: integer ++
optional: true ++
default: 100 ++
description: maximum value of the slider range ++
min_limit: ++
type: integer ++
optional: true ++
default: 0 ++
description: limit minimum value of the slider ++
max_limit: ++
type: integer ++
optional: true ++
default: 100 ++
description: limit maximum value of the slider ++
value_scale: ++
type: integer ++
optional: true ++
default: 0 ++
description: scale small value, slider round digits ++
description: general slider control ++
#START pulse-audio
*volume*++
type: object ++
Expand Down
64 changes: 57 additions & 7 deletions src/configSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@
"^menubar(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/menubar"
},
"^slider(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/slider"
},
"^volume(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/volume"
},
Expand Down Expand Up @@ -446,9 +449,9 @@
"default": ""
},
"active": {
"type": "boolean",
"description": "Wether the toggle button is active as default or not",
"default": false
"type": "boolean",
"description": "Wether the toggle button is active as default or not",
"default": false
}
}
}
Expand Down Expand Up @@ -482,13 +485,13 @@
"description": "Animation type for menu",
"enum": ["slide_down", "slide_up", "none"]
},
"animation-duration":{
"animation-duration": {
"type": "integer",
"default": 250,
"description": "Duration of animation in milliseconds"
},
"actions": {
"$ref" : "#/widgets/buttons-grid/properties/actions"
"$ref": "#/widgets/buttons-grid/properties/actions"
}
}
},
Expand All @@ -504,12 +507,59 @@
"enum": ["right", "left"]
},
"actions": {
"$ref" : "#/widgets/buttons-grid/properties/actions"
"$ref": "#/widgets/buttons-grid/properties/actions"
}
}
}
}
},
"slider": {
"type": "object",
"description": "general slider control",
"additionalProperties": false,
"properties": {
"label": {
"type": "string",
"description": "Text displayed in front of the slider",
"default": "slider"
},
"cmd_setter": {
"type": "string",
"description": "command to set the value",
"default": ""
},
"cmd_getter": {
"type": "string",
"description": "command to get the actual value",
"default": ""
},
"min": {
"type": "integer",
"description": "minimum value of the slider range",
"default": 0
},
"max": {
"type": "integer",
"description": "maximum value of the slider range",
"default": 100
},
"min_limit": {
"type": "integer",
"description": "limit minimum value of the slider",
"default": 0
},
"max_limit": {
"type": "integer",
"description": "limit maximum value of the slider",
"default": 100
},
"value_scale": {
"type": "integer",
"default": 0,
"description": "scale small value, slider round digits"
}
}
},
"volume": {
"type": "object",
"description": "Slider to control pulse volume",
Expand Down Expand Up @@ -561,7 +611,7 @@
"description": "Animation type for menu",
"enum": ["slide_down", "slide_up", "none"]
},
"animation-duration":{
"animation-duration": {
"type": "integer",
"default": 250,
"description": "Duration of animation in milliseconds"
Expand Down
3 changes: 3 additions & 0 deletions src/controlCenter/widgets/factory.vala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ namespace SwayNotificationCenter.Widgets {
case "buttons-grid":
widget = new ButtonsGrid (suffix, swaync_daemon, noti_daemon);
break;
case "slider":
widget = new Slider (suffix, swaync_daemon, noti_daemon);
break;
#if HAVE_PULSE_AUDIO
case "volume":
widget = new Volume (suffix, swaync_daemon, noti_daemon);
Expand Down
139 changes: 139 additions & 0 deletions src/controlCenter/widgets/slider/slider.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
namespace SwayNotificationCenter.Widgets {
public class Slider : BaseWidget {
public override string widget_name {
get {
return "slider";
}
}

Gtk.Label label_widget = new Gtk.Label (null);
Gtk.Scale slider = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);

private double min_limit;
private double max_limit;
private double ? last_set;
private bool cmd_ing = false;

private string cmd_setter;
private string cmd_getter;

public Slider (string suffix, SwayncDaemon swaync_daemon, NotiDaemon noti_daemon) {
base (suffix, swaync_daemon, noti_daemon);

int ? round_digits = 0;

Json.Object ? config = get_config (this);
if (config != null) {
string ? label = get_prop<string> (config, "label");
label_widget.set_label (label ?? "Slider");

cmd_setter = get_prop<string> (config, "cmd_setter") ?? "";
cmd_getter = get_prop<string> (config, "cmd_getter") ?? "";

int ? min = get_prop<int> (config, "min");
int ? max = get_prop<int> (config, "max");
int ? maxl = get_prop<int> (config, "max_limit");
int ? minl = get_prop<int> (config, "min_limit");
round_digits = get_prop<int> (config, "value_scale");

if (min == null)min = 0;
if (max == null)max = 100;
if (round_digits == null)round_digits = 0;

max_limit = maxl != null ? double.min (max, maxl) : max;

min_limit = minl != null ? double.max (min, minl) : min;

double scale = Math.pow (10, round_digits);

min_limit /= scale;
max_limit /= scale;

slider.set_range (min / scale, max / scale);
}

slider.set_draw_value (false);
slider.set_round_digits (round_digits);
slider.value_changed.connect (() => {
double value = slider.get_value ();
if (value > max_limit)
value = max_limit;
if (value < min_limit)
value = min_limit;

slider.set_value (value);
slider.tooltip_text = value.to_string ();

if (cmd_setter != "" && last_set != value) {
last_set = value;
queue_set.begin (value);
}
});

add (label_widget);
pack_start (slider, true, true, 0);

show_all ();
}

public string expand_cmd (string cmd, string regex, string value) {
try {
Regex _regx = new Regex (Regex.escape_string (regex));
return _regx.replace_literal (cmd, -1, 0, value);
} catch (Error e) {
warning ("failed to expand cmd: %s\n", e.message);
return cmd;
}
}

public async void queue_set (double value) {
if (cmd_ing)
return;

cmd_ing = true;
var cmd = expand_cmd (cmd_setter, "$value", value.to_string ());
yield Functions.execute_command (cmd, {}, null);

cmd_ing = false;

// make sure the last_set is applied
if (value != last_set) {
yield queue_set (last_set);
}
}

public async void queue_get (int retry, out string value) {
if (cmd_ing) {
if (retry <= 0) {
value = "";
return;
}
yield queue_get (retry - 1, out value);
}

cmd_ing = true;
yield Functions.execute_command (cmd_getter, {}, out value);

cmd_ing = false;
}

public async void on_update () {
if (cmd_getter == "")
return;

string value_str = "";
yield queue_get (4, out value_str);

double value = double.parse (value_str);
if (value <= max_limit && value >= min_limit) {
last_set = value;
slider.set_value (value);
}
}

public override void on_cc_visibility_change (bool value) {
if (value)
on_update.begin ();
}
}
}
3 changes: 3 additions & 0 deletions src/functions.vala
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ namespace SwayNotificationCenter {
string[] argvp = {};
Shell.parse_argv (cmd, out argvp);

if (argvp[0].has_prefix ("~"))
argvp[0] = Environment.get_home_dir () + argvp[0].substring (1);

Pid child_pid;
int std_output;
Process.spawn_async_with_pipes (
Expand Down
2 changes: 2 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ widget_sources = [
'controlCenter/widgets/menubar/menubar.vala',
# Widget: Buttons Grid
'controlCenter/widgets/buttonsGrid/buttonsGrid.vala',
# Widget: Slider
'controlCenter/widgets/slider/slider.vala',
# Widget: Backlight Slider
'controlCenter/widgets/backlight/backlight.vala',
'controlCenter/widgets/backlight/backlightUtil.vala',
Expand Down
Loading