Skip to content
Draft
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
14 changes: 5 additions & 9 deletions data/Application.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,12 @@ row.task.drag-active {
min-width: 86px; /* https://github.com/elementary/granite/issues/577#issuecomment-1318979272 */
}

.source-color {
background: @colorAccent;
border: 1px solid @borders;
.circular-progress-bar {
border: 2px solid @accent_color;
border-radius: 50%;
box-shadow:
inset 0 1px 0 0 alpha(@inset_dark_color, 0.7),
inset 0 0 0 1px alpha(@inset_dark_color, 0.3),
0 1px 0 0 alpha(@bg_highlight_color, 0.3);
min-height: 14px;
min-width: 14px;
min-width: 8px;
min-height: 8px;
padding: 2px;
}

.sidebar image {
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ executable(
'src/Util.vala',
'src/Views/ListView.vala',
'src/Views/ScheduledView.vala',
'src/Widgets/CircularProgressBar.vala',
'src/Widgets/EditableLabel.vala',
'src/Widgets/EntryPopover/DateTime.vala',
'src/Widgets/EntryPopover/Generic.vala',
Expand Down
218 changes: 218 additions & 0 deletions src/Widgets/CircularProgressBar.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/* -*- Mode: Vala; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab : */
/*
* Custom Gtk.Widget to provide a circular progress bar.
* It extends/subclasses Gtk.Bin instead of Gtk.DrawingArea.
*
* Based on José Miguel Fonte's Vala Circular Progress Bar
* https://github.com/phastmike/vala-circular-progress-bar
*/

using Gtk;
using Cairo;

public class Tasks.CircularProgressBar : Granite.Bin {
public double percentage {
get {
return circularProgressBar.percentage;
}

set {
circularProgressBar.percentage = value;
}
}

public string color {
set {
circularProgressBar.progress_fill_color = value;
}
}

private _CircularProgressBar circularProgressBar; // vala-lint=naming-convention

public CircularProgressBar () {
}

construct {
add_css_class ("circular-progress-bar");

circularProgressBar = new _CircularProgressBar ();

child = circularProgressBar;
}
}

public class _CircularProgressBar : Gtk.DrawingArea { // vala-lint=naming-convention
private int _line_width;
private double _percentage;
private string _center_fill_color;
private string _radius_fill_color;
private string _progress_fill_color;

[Description (nick = "Center Fill", blurb = "Center Fill toggle")]
public bool center_filled {set; get; default = false;}

[Description (nick = "Radius Fill", blurb = "Radius Fill toggle")]
public bool radius_filled {set; get; default = false;}

[Description (nick = "Line Cap", blurb = "Line Cap for stroke as in Cairo.LineCap")]
public Cairo.LineCap line_cap {set; get; default = Cairo.LineCap.BUTT;}

[Description (nick = "Inside circle fill color", blurb = "Center pad fill color (Check Gdk.RGBA parse method)")]
public string center_fill_color {
get {
return _center_fill_color;
}
set {
var color = Gdk.RGBA ();
if (color.parse (value)) {
_center_fill_color = value;
}
}
}

[Description (nick = "Circular radius fill color", blurb = "The circular pad fill color (Check GdkRGBA parse method)")]
public string radius_fill_color {
get {
return _radius_fill_color;
}
set {
var color = Gdk.RGBA ();
if (color.parse (value)) {
_radius_fill_color = value;
}
}
}

[Description (nick = "Progress fill color", blurb = "Progress line color (Check GdkRGBA parse method)")]
public string progress_fill_color {
get {
return _progress_fill_color;
}
set {
var color = Gdk.RGBA ();
if (color.parse (value)) {
_progress_fill_color = value;
}
}
}

[Description (nick = "Circle width", blurb = "The circle radius line width")]
public int line_width {
get {
return _line_width;
}
set {
if (value < 0) {
_line_width = 0;
} else if (value > calculate_radius ()) {
_line_width = calculate_radius ();
} else {
_line_width = value;
}
}
}

[Description (nick = "Percentage/Value", blurb = "The percentage value [0.0 ... 1.0]")]
public double percentage {
get {
return _percentage;
}
set {
if (value > 1.0) {
_percentage = 1.0;
} else if (value < 0.0) {
_percentage = 0.0;
} else {
_percentage = value;
}
}
}

construct {
_line_width = 0;
_percentage = 0.5;
_center_fill_color = "#adadad"; // vala-lint=double-spaces
_radius_fill_color = "#d3d3d3"; // vala-lint=double-spaces
_progress_fill_color = "#4a90d9";
}

public _CircularProgressBar () {
set_draw_func (draw);

notify.connect (() => {
queue_draw ();
});
}

private int calculate_radius () {
return int.min (get_width () / 2, get_height () / 2) - 1;
}

public override Gtk.SizeRequestMode get_request_mode () {
return Gtk.SizeRequestMode.CONSTANT_SIZE;
}

public void draw (DrawingArea da, Cairo.Context cr, int width, int height) {
int delta;
Gdk.RGBA color;

cr.save ();

color = Gdk.RGBA ();

var center_x = get_width () / 2;
var center_y = get_height () / 2;
var radius = calculate_radius ();

if (radius - line_width < 0) {
delta = 0;
line_width = radius;
} else {
delta = radius - (line_width / 2);
}

color = Gdk.RGBA ();
cr.set_line_cap (line_cap);
cr.set_line_width (line_width);

// Center Fill
if (center_filled == true) {
cr.arc (center_x, center_y, delta, 0, 2 * Math.PI);
color.parse (center_fill_color);
Gdk.cairo_set_source_rgba (cr, color);
cr.fill ();
}

// Radius Fill
if (radius_filled == true) {
cr.arc (center_x, center_y, delta, 0, 2 * Math.PI);
color.parse (radius_fill_color);
Gdk.cairo_set_source_rgba (cr, color);
cr.stroke ();
}

// Progress/Percentage Fill
if (percentage > 0) {
color.parse (progress_fill_color);
Gdk.cairo_set_source_rgba (cr, color);

if (line_width == 0) {
cr.move_to (center_x, center_y);
cr.arc (center_x,
center_y,
delta + 1,
1.5 * Math.PI,
(1.5 + percentage * 2 ) * Math.PI);
cr.fill ();
} else {
cr.arc (center_x,
center_y,
delta,
1.5 * Math.PI,
(1.5 + percentage * 2 ) * Math.PI);
cr.stroke ();
}
}
}
}
15 changes: 8 additions & 7 deletions src/Widgets/SourceRow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
public E.Source source { get; construct; }

private Gtk.Grid source_color;
private CircularProgressBar progress_circle;
private Gtk.Image status_image;
private Gtk.Label display_name_label;
private Gtk.Stack status_stack;
Expand All @@ -17,10 +17,7 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
}

construct {
source_color = new Gtk.Grid () {
valign = Gtk.Align.CENTER
};
source_color.add_css_class ("source-color");
progress_circle = new CircularProgressBar ();

display_name_label = new Gtk.Label (source.display_name) {
halign = Gtk.Align.START,
Expand All @@ -44,7 +41,7 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6) {
margin_end = 6
};
box.append (source_color);
box.append (progress_circle);
box.append (display_name_label);
box.append (status_stack);

Expand Down Expand Up @@ -162,7 +159,11 @@ public class Tasks.Widgets.SourceRow : Gtk.ListBoxRow {
}

public void update_request () {
Tasks.Application.set_task_color (source, source_color);
Tasks.Application.set_task_color (source, progress_circle);

unowned var task_list = (E.SourceTaskList?) source.get_extension (E.SOURCE_EXTENSION_TASK_LIST);
// Ensure we get a valid CSS color, not including FF
progress_circle.color = task_list.dup_color ().slice (0, 7);

display_name_label.label = source.display_name;

Expand Down