[gnome-clocks/wip/analogtimer] Experiment with a circular progress for timer
- From: Paolo Borelli <pborelli src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-clocks/wip/analogtimer] Experiment with a circular progress for timer
- Date: Fri, 2 Aug 2013 12:01:20 +0000 (UTC)
commit 352b5910f5732b0ea087c7df0b8f14be33f7a345
Author: Paolo Borelli <pborelli gnome org>
Date: Mon Jul 29 13:08:23 2013 +0200
Experiment with a circular progress for timer
This is an experiment to play with the idea of showing some kind of
progress to spice up the timer panel.
src/timer.vala | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 139 insertions(+), 10 deletions(-)
---
diff --git a/src/timer.vala b/src/timer.vala
index 0b1b36e..508664e 100644
--- a/src/timer.vala
+++ b/src/timer.vala
@@ -19,6 +19,126 @@
namespace Clocks {
namespace Timer {
+public class CountdownFrame : Gtk.Frame {
+ private const int RADIUS_PAD = 36;
+
+ public double span { get; set; default = 0; }
+
+ private double elapsed;
+ private double elapsed_before_pause;
+ private Cairo.Pattern cursor_pattern;
+
+ private double get_progress () {
+ return span != 0 ? (elapsed_before_pause + elapsed) / span : 0;
+ }
+
+ private int calculate_diameter () {
+ var child = get_child ();
+ if (child != null && child.visible) {
+ int w, h;
+ child.get_preferred_width (out w, null);
+ child.get_preferred_height (out h, null);
+ return RADIUS_PAD + (int) Math.sqrt (w * w + h * h);
+ } else {
+ return RADIUS_PAD;
+ }
+ }
+
+ public void update (double e) {
+ elapsed = e;
+ queue_draw ();
+ }
+
+ public void pause () {
+ elapsed_before_pause += elapsed;
+ elapsed = 0;
+ }
+
+ public override void get_preferred_width (out int min_w, out int natural_w) {
+ var d = calculate_diameter ();
+ min_w = d;
+ natural_w = d;
+ }
+
+ public override void get_preferred_height (out int min_h, out int natural_h) {
+ var d = calculate_diameter ();
+ min_h = d;
+ natural_h = d;
+ }
+
+ public override void size_allocate (Gtk.Allocation allocation) {
+ set_allocation (allocation);
+ var child = get_child ();
+ if (child != null && child.visible) {
+ int w, h;
+ child.get_preferred_width (out w, null);
+ child.get_preferred_height (out h, null);
+
+ Gtk.Allocation child_allocation = {};
+ child_allocation.x = allocation.x + (allocation.width - w) / 2;
+ child_allocation.y = allocation.y + (allocation.height - h) / 2;
+ child_allocation.width = w;
+ child_allocation.height = h;
+ child.size_allocate (child_allocation);
+ }
+ }
+
+ public override bool draw (Cairo.Context cr) {
+ base.draw(cr);
+
+ var context = get_style_context ();
+ Gtk.Allocation allocation;
+ get_allocation (out allocation);
+ var center_x = allocation.width / 2;
+ var center_y = allocation.height / 2;
+
+ var radius = calculate_diameter () / 2;
+ cr.move_to (center_x + radius, center_y);
+
+ cr.set_line_width (1);
+ var color = context.get_border_color (Gtk.StateFlags.SELECTED);
+ Gdk.cairo_set_source_rgba (cr, color);
+ cr.arc (center_x, center_y, radius, 0, 2 * Math.PI);
+ cr.arc (center_x, center_y, radius - 9, 0, 2 * Math.PI);
+ cr.stroke ();
+
+ cr.set_line_width (8);
+
+ color = context.get_color (Gtk.StateFlags.SELECTED);
+ cr.arc (center_x, center_y, radius - 4.5, 0, 2 * Math.PI);
+ Gdk.cairo_set_source_rgba (cr, color);
+ cr.stroke ();
+
+ var progress = get_progress ();
+ if (progress > 0) {
+ color = context.get_background_color (Gtk.StateFlags.SELECTED);
+ cr.arc (center_x, center_y, radius - 4.5, 1.5 * Math.PI, (1.5 + progress * 2 ) * Math.PI);
+ Gdk.cairo_set_source_rgba (cr, color);
+ cr.stroke ();
+
+ if (progress < 1) {
+ if (cursor_pattern == null) {
+ cursor_pattern = new Cairo.Pattern.radial (0, 0, 6, 0, 0, 18);
+ cursor_pattern.add_color_stop_rgba (0, color.red, color.green, color.blue, 1);
+ cursor_pattern.add_color_stop_rgba (0.5, color.red, color.green, color.blue, 0);
+ }
+
+ var x = center_x + (radius - 4.5) * Math.cos((1.5 + progress * 2) * Math.PI);
+ var y = center_y + (radius - 4.5) * Math.sin((1.5 + progress * 2) * Math.PI);
+
+ var cursor_radius = 18;
+ cr.arc (x, y, cursor_radius, 0, 2 * Math.PI);
+ cr.translate (x, y);
+ cr.set_source (cursor_pattern);
+ cr.fill ();
+ }
+ }
+
+ return false;
+ }
+
+}
+
public class MainPanel : Gtk.Stack, Clocks.Clock {
enum State {
STOPPED,
@@ -39,7 +159,7 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
private Gtk.SpinButton m_spinbutton;
private Gtk.SpinButton s_spinbutton;
private Gtk.Button start_button;
- private Gtk.Widget countdown_panel;
+ private CountdownFrame countdown_frame;
private Gtk.Label time_label;
private Gtk.Button left_button;
private Gtk.Button right_button;
@@ -77,7 +197,12 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
start ();
});
- countdown_panel = builder.get_object ("countdown_panel") as Gtk.Widget;
+ countdown_frame = new CountdownFrame ();
+ countdown_frame.show();
+
+ var countdown_widgets = builder.get_object ("countdown_panel") as Gtk.Widget;
+ countdown_frame.add (countdown_widgets);
+
time_label = builder.get_object ("time_label") as Gtk.Label;
left_button = builder.get_object ("left_button") as Gtk.Button;
right_button = builder.get_object ("right_button") as Gtk.Button;
@@ -105,7 +230,7 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
});
add (setup_panel);
- add (countdown_panel);
+ add (countdown_frame);
reset ();
@@ -160,7 +285,9 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
settings.set_uint ("timer", (uint) span);
timer.start ();
- visible_child = countdown_panel;
+
+ countdown_frame.span = span;
+ visible_child = countdown_frame;
update_countdown_label (h, m, s);
add_timeout ();
@@ -177,23 +304,24 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
state = State.PAUSED;
timer.stop ();
span -= timer.elapsed ();
+ countdown_frame.pause ();
remove_timeout ();
}
private void add_timeout () {
if (timeout_id == 0) {
- timeout_id = Timeout.add (100, count);
+ timeout_id = add_tick_callback ((Gtk.TickCallback)count);
}
}
private void remove_timeout () {
if (timeout_id != 0) {
- Source.remove (timeout_id);
+ remove_tick_callback (timeout_id);
timeout_id = 0;
}
}
- private bool count () {
+ private bool count (Gdk.FrameClock frame_clock) {
var e = timer.elapsed ();
if (e >= span) {
ring ();
@@ -204,22 +332,23 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
return false;
}
- update_countdown (span - e);
+ update_countdown (e);
return true;
}
- private void update_countdown (double t) {
+ private void update_countdown (double elapsed) {
if (time_label.get_mapped ()) {
// Math.ceil() because we count backwards:
// with 0.3 seconds we want to show 1 second remaining,
// with 59.2 seconds we want to show 1 minute, etc
- t = Math.ceil (t);
+ double t = Math.ceil (span - elapsed);
int h;
int m;
int s;
double r;
Utils.time_to_hms (t, out h, out m, out s, out r);
update_countdown_label (h, m, s);
+ countdown_frame.update (elapsed);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]