[gnome-clocks/wip/analogstopwatchtimer: 2/3] Add analog progress to the timer



commit 73a8e6e8afc9ad61fb6d20f6a33cd0510ccaef3d
Author: Paolo Borelli <pborelli gnome org>
Date:   Thu Aug 15 11:18:57 2013 +0200

    Add analog progress to the timer
    
    Add a circle around the timer showing the analog progess of the the countdown.

 data/css/gnome-clocks.css |    4 +
 data/ui/timer.ui          |  336 ++++++++++++++++++++++++---------------------
 src/timer.vala            |   78 +++++++++--
 3 files changed, 246 insertions(+), 172 deletions(-)
---
diff --git a/data/css/gnome-clocks.css b/data/css/gnome-clocks.css
index 17c2b71..6e5dc7e 100644
--- a/data/css/gnome-clocks.css
+++ b/data/css/gnome-clocks.css
@@ -189,6 +189,10 @@
     color: #d3d7cf;
 }
 
+.clocks-analog-frame.progress {
+    color: #2e3436;
+}
+
 .view.clocks-laps {
     font-size: larger;
     background-color: @theme_bg_color;
diff --git a/data/ui/timer.ui b/data/ui/timer.ui
index 6f3c419..ed99b5f 100644
--- a/data/ui/timer.ui
+++ b/data/ui/timer.ui
@@ -16,35 +16,131 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
-  <object class="GtkGrid" id="setup_panel">
+  <object class="ClocksAnalogFrame" id="setup_frame">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="halign">center</property>
-    <property name="valign">center</property>
-    <property name="hexpand">True</property>
-    <property name="vexpand">True</property>
-    <property name="row_spacing">48</property>
+    <property name="margin_left">48</property>
+    <property name="margin_right">48</property>
+    <property name="margin_top">48</property>
+    <property name="margin_bottom">48</property>
     <child>
-      <object class="GtkGrid" id="grid_spinbuttons">
+      <object class="GtkGrid" id="setup_grid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">center</property>
         <property name="valign">center</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="row_spacing">48</property>
         <child>
-          <object class="GtkSpinButton" id="spinbutton_hours">
+          <object class="GtkGrid" id="grid_spinbuttons">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="invisible_char">●</property>
-            <property name="xalign">0.5</property>
-            <property name="invisible_char_set">True</property>
-            <property name="input_purpose">number</property>
-            <property name="orientation">vertical</property>
-            <property name="adjustment">adjustment_hours</property>
-            <property name="numeric">True</property>
-            <property name="wrap">True</property>
-            <style>
-              <class name="clocks-spinbutton"/>
-            </style>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <child>
+              <object class="GtkSpinButton" id="spinbutton_hours">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">●</property>
+                <property name="xalign">0.5</property>
+                <property name="invisible_char_set">True</property>
+                <property name="input_purpose">number</property>
+                <property name="orientation">vertical</property>
+                <property name="adjustment">adjustment_hours</property>
+                <property name="numeric">True</property>
+                <property name="wrap">True</property>
+                <style>
+                  <class name="clocks-spinbutton"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="spinbutton_minutes">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">●</property>
+                <property name="xalign">0.5</property>
+                <property name="invisible_char_set">True</property>
+                <property name="input_purpose">number</property>
+                <property name="orientation">vertical</property>
+                <property name="adjustment">adjustment_minutes</property>
+                <property name="numeric">True</property>
+                <property name="wrap">True</property>
+                <style>
+                  <class name="clocks-spinbutton"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="spinbutton_seconds">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">●</property>
+                <property name="xalign">0.5</property>
+                <property name="invisible_char_set">True</property>
+                <property name="input_purpose">number</property>
+                <property name="orientation">vertical</property>
+                <property name="adjustment">adjustment_seconds</property>
+                <property name="numeric">True</property>
+                <property name="wrap">True</property>
+                <style>
+                  <class name="clocks-spinbutton"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">4</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="colon_label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="label">∶</property>
+                <attributes>
+                  <attribute name="font-desc" value="64"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="colon_label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="label">∶</property>
+                <attributes>
+                  <attribute name="font-desc" value="64"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left_attach">3</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="left_attach">0</property>
@@ -54,152 +150,51 @@
           </packing>
         </child>
         <child>
-          <object class="GtkSpinButton" id="spinbutton_minutes">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="invisible_char">●</property>
-            <property name="xalign">0.5</property>
-            <property name="invisible_char_set">True</property>
-            <property name="input_purpose">number</property>
-            <property name="orientation">vertical</property>
-            <property name="adjustment">adjustment_minutes</property>
-            <property name="numeric">True</property>
-            <property name="wrap">True</property>
-            <style>
-              <class name="clocks-spinbutton"/>
-            </style>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkSpinButton" id="spinbutton_seconds">
+          <object class="GtkButton" id="start_button">
+            <property name="label" translatable="yes">Start</property>
+            <property name="width_request">200</property>
             <property name="visible">True</property>
             <property name="can_focus">True</property>
-            <property name="invisible_char">●</property>
-            <property name="xalign">0.5</property>
-            <property name="invisible_char_set">True</property>
-            <property name="input_purpose">number</property>
-            <property name="orientation">vertical</property>
-            <property name="adjustment">adjustment_seconds</property>
-            <property name="numeric">True</property>
-            <property name="wrap">True</property>
+            <property name="receives_default">True</property>
             <style>
-              <class name="clocks-spinbutton"/>
+              <class name="clocks-button"/>
             </style>
           </object>
           <packing>
-            <property name="left_attach">4</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="colon_label1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="hexpand">True</property>
-            <property name="label">∶</property>
-            <attributes>
-              <attribute name="font-desc" value="64"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="colon_label2">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="hexpand">True</property>
-            <property name="label">∶</property>
-            <attributes>
-              <attribute name="font-desc" value="64"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">3</property>
-            <property name="top_attach">0</property>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
             <property name="width">1</property>
             <property name="height">1</property>
           </packing>
         </child>
       </object>
-      <packing>
-        <property name="left_attach">0</property>
-        <property name="top_attach">0</property>
-        <property name="width">1</property>
-        <property name="height">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkButton" id="start_button">
-        <property name="label" translatable="yes">Start</property>
-        <property name="width_request">200</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="receives_default">True</property>
-        <style>
-          <class name="clocks-button"/>
-        </style>
-      </object>
-      <packing>
-        <property name="left_attach">0</property>
-        <property name="top_attach">1</property>
-        <property name="width">1</property>
-        <property name="height">1</property>
-      </packing>
     </child>
   </object>
-  <object class="GtkGrid" id="countdown_panel">
+  <object class="ClocksTimerCountdownFrame" id="countdown_frame">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="halign">center</property>
-    <property name="valign">center</property>
-    <property name="hexpand">True</property>
-    <property name="vexpand">True</property>
-    <property name="row_spacing">48</property>
-    <property name="column_spacing">24</property>
+    <property name="margin_left">48</property>
+    <property name="margin_right">48</property>
+    <property name="margin_top">48</property>
+    <property name="margin_bottom">48</property>
     <child>
-      <object class="GtkLabel" id="countdown_label">
+      <object class="GtkGrid" id="countdown_grid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">center</property>
         <property name="valign">center</property>
-        <style>
-          <class name="clocks-time-label"/>
-        </style>
-      </object>
-      <packing>
-        <property name="left_attach">0</property>
-        <property name="top_attach">0</property>
-        <property name="width">1</property>
-        <property name="height">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkGrid" id="button_grid">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="row_spacing">48</property>
         <property name="column_spacing">24</property>
         <child>
-          <object class="GtkButton" id="left_button">
-            <property name="label" translatable="yes">Pause</property>
-            <property name="width_request">200</property>
+          <object class="GtkLabel" id="countdown_label">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
             <style>
-              <class name="clocks-button"/>
+              <class name="clocks-time-label"/>
             </style>
           </object>
           <packing>
@@ -210,30 +205,55 @@
           </packing>
         </child>
         <child>
-          <object class="GtkButton" id="right_button">
-            <property name="label" translatable="yes">Reset</property>
-            <property name="width_request">200</property>
+          <object class="GtkGrid" id="button_grid">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <style>
-              <class name="clocks-button"/>
-            </style>
+            <property name="can_focus">False</property>
+            <property name="column_spacing">24</property>
+            <child>
+              <object class="GtkButton" id="left_button">
+                <property name="label" translatable="yes">Pause</property>
+                <property name="width_request">200</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <style>
+                  <class name="clocks-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="right_button">
+                <property name="label" translatable="yes">Reset</property>
+                <property name="width_request">200</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <style>
+                  <class name="clocks-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
           </object>
           <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">0</property>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
             <property name="width">1</property>
             <property name="height">1</property>
           </packing>
         </child>
       </object>
-      <packing>
-        <property name="left_attach">0</property>
-        <property name="top_attach">1</property>
-        <property name="width">1</property>
-        <property name="height">1</property>
-      </packing>
     </child>
   </object>
   <object class="GtkSizeGroup" id="sizegroup1">
diff --git a/src/timer.vala b/src/timer.vala
index 4a3b9ed..117cd71 100644
--- a/src/timer.vala
+++ b/src/timer.vala
@@ -19,6 +19,51 @@
 namespace Clocks {
 namespace Timer {
 
+public class CountdownFrame : AnalogFrame {
+    public double span { get; set; default = 0; }
+
+    private double elapsed;
+    private double elapsed_before_pause;
+
+    private double get_progress () {
+        return span != 0 ? (elapsed_before_pause + elapsed) / span : 0;
+    }
+
+    public void update (double e) {
+        elapsed = e;
+        queue_draw ();
+    }
+
+    public void pause () {
+        elapsed_before_pause += elapsed;
+        elapsed = 0;
+    }
+
+    public void reset () {
+        elapsed_before_pause = 0;
+        elapsed = 0;
+    }
+
+    public override void draw_progress (Cairo.Context cr, int center_x, int center_y, int radius) {
+        var context = get_style_context ();
+
+        context.save ();
+        context.add_class ("progress");
+
+        cr.set_line_width (LINE_WIDTH);
+        cr.set_line_cap  (Cairo.LineCap.ROUND);
+
+        var color = context.get_color (Gtk.StateFlags.NORMAL);
+
+        var progress = get_progress ();
+        cr.arc (center_x, center_y, radius - LINE_WIDTH / 2, 1.5  * Math.PI, (1.5 + (1 - progress) * 2 ) * 
Math.PI);
+        Gdk.cairo_set_source_rgba (cr, color);
+        cr.stroke ();
+
+        context.restore ();
+    }
+}
+
 public class MainPanel : Gtk.Stack, Clocks.Clock {
     enum State {
         STOPPED,
@@ -34,13 +79,13 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
     private GLib.Settings settings;
     private uint tick_id;
     private Utils.Bell bell;
-    private Gtk.Widget setup_panel;
     private Gtk.Grid grid_spinbuttons;
     private Gtk.SpinButton h_spinbutton;
     private Gtk.SpinButton m_spinbutton;
     private Gtk.SpinButton s_spinbutton;
     private Gtk.Button start_button;
-    private Gtk.Widget countdown_panel;
+    private AnalogFrame setup_frame;
+    private CountdownFrame countdown_frame;
     private Gtk.Label countdown_label;
     private Gtk.Button left_button;
     private Gtk.Button right_button;
@@ -60,7 +105,7 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
 
         var builder = Utils.load_ui ("timer.ui");
 
-        setup_panel = builder.get_object ("setup_panel") as Gtk.Widget;
+        setup_frame = builder.get_object ("setup_frame") as AnalogFrame;
         grid_spinbuttons = builder.get_object ("grid_spinbuttons") as Gtk.Grid;
         h_spinbutton = builder.get_object ("spinbutton_hours") as Gtk.SpinButton;
         m_spinbutton = builder.get_object ("spinbutton_minutes") as Gtk.SpinButton;
@@ -82,7 +127,7 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
             start ();
         });
 
-        countdown_panel = builder.get_object ("countdown_panel") as Gtk.Widget;
+        countdown_frame = builder.get_object ("countdown_frame") as CountdownFrame;
         countdown_label = builder.get_object ("countdown_label") as Gtk.Label;
         left_button = builder.get_object ("left_button") as Gtk.Button;
         right_button = builder.get_object ("right_button") as Gtk.Button;
@@ -109,12 +154,12 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
             left_button.set_label (_("Pause"));
         });
 
-        add (setup_panel);
-        add (countdown_panel);
+        add (setup_frame);
+        add (countdown_frame);
 
         reset ();
 
-        visible_child = setup_panel;
+        visible_child = setup_frame;
         show_all ();
     }
 
@@ -150,7 +195,8 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
         m_spinbutton.value = (int) span / 60;
         s_spinbutton.value = span % 60;
         start_button.set_sensitive (span > 0);
-        visible_child = setup_panel;
+        countdown_frame.reset ();
+        visible_child = setup_frame;
     }
 
     private void start () {
@@ -165,7 +211,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_tick ();
@@ -182,6 +230,7 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
         state = State.PAUSED;
         timer.stop ();
         span -= timer.elapsed ();
+        countdown_frame.pause ();
         remove_tick ();
     }
 
@@ -207,26 +256,27 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
             state = State.STOPPED;
             remove_tick ();
             update_countdown_label (0, 0, 0);
-            visible_child = setup_panel;
+            visible_child = setup_frame;
             return false;
         }
 
-        update_countdown (span - e);
+        update_countdown (e);
         return true;
     }
 
-    private void update_countdown (double t) {
+    private void update_countdown (double elapsed) {
         if (countdown_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);
         }
     }
 
@@ -237,7 +287,7 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
     }
 
     public override void grab_focus () {
-        if (visible_child == setup_panel) {
+        if (visible_child == setup_frame) {
             start_button.grab_focus ();
         }
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]