5129c8d340edcbb38d2a73353431fdd067fd90c3
[stopish] / src / stopish-stopwatch.c
1 //      stopish-stopwatch.c
2 //
3 //      Copyright 2010 Michael Cronenworth <mike@cchtml.com>
4 //
5 //      This program is free software; you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation; either version 2 of the License, or
8 //      (at your option) any later version.
9 //
10 //      This program is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with this program; if not, write to the Free Software
17 //      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 //      MA 02110-1301, USA.
19
20 #include <gtk/gtk.h>
21 #include <hildon/hildon.h>
22 #include <stdlib.h>
23
24 #include "stopish.h"
25
26 struct timerData {
27     GtkWidget *vBox;
28     GtkWidget *label;
29     GtkWidget *labelHour;
30     GtkWidget *labelMinute;
31     GtkWidget *labelSecond;
32 };
33
34 static struct timerData timerdata;
35 static GtkWidget *timerHistoryLabel1 = NULL;
36 static GtkWidget *timerHistoryLabel2 = NULL;
37 static GtkWidget *timerHistoryLabel3 = NULL;
38 static GtkWidget *timerHistoryLabel4 = NULL;
39 static GSList *historyList = NULL;
40 static int timerHandle = -1;
41
42
43 static gint timeout_cb( gpointer data );
44 static void start_cb( GtkButton* button, gpointer data );
45 static void reset_cb( GtkButton* button, gpointer data );
46
47
48 GtkWindow *stopish_stopwatch_new( void )
49 {
50     GtkWidget *window, *button, *button0, *label;
51     GtkWidget *vBoxMain, *vBox0, *hBox0;
52
53     window = hildon_stackable_window_new(  );
54
55     gtk_container_set_border_width( GTK_CONTAINER( window ), 20 );
56
57     gtk_window_set_title( GTK_WINDOW( window ), "Stopish" );
58
59     vBoxMain = gtk_vbox_new( FALSE, 10 );
60
61     // separator
62     label = gtk_label_new( NULL );
63     gtk_container_add( GTK_CONTAINER( vBoxMain ), label );
64
65     vBox0 = gtk_vbox_new( FALSE, 5 );
66
67     // stop watch area
68     timerdata.vBox = gtk_vbox_new( FALSE, 0 );
69     gtk_container_add( GTK_CONTAINER( vBox0 ), timerdata.vBox );
70     stopish_stopwatch_label_timer_landscape(  );
71
72     // history area
73     timerHistoryLabel1 = gtk_label_new( NULL );
74     gtk_label_set_markup( GTK_LABEL( timerHistoryLabel1 ),
75                           "<span size=\"large\"> </span>" );
76     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel1, FALSE, FALSE, 0 );
77     timerHistoryLabel2 = gtk_label_new( NULL );
78     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel2, FALSE, FALSE, 0 );
79     timerHistoryLabel3 = gtk_label_new( NULL );
80     gtk_label_set_markup( GTK_LABEL( timerHistoryLabel3 ),
81                           "<span size=\"small\"> </span>" );
82     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel3, FALSE, FALSE, 0 );
83     timerHistoryLabel4 = gtk_label_new( NULL );
84     gtk_label_set_markup( GTK_LABEL( timerHistoryLabel4 ),
85                           "<span size=\"x-small\"> </span>" );
86     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel4, FALSE, FALSE, 0 );
87
88     gtk_container_add( GTK_CONTAINER( vBoxMain ), vBox0 );
89
90     // separator
91     label = gtk_label_new( NULL );
92     gtk_container_add( GTK_CONTAINER( vBoxMain ), label );
93
94     // button area
95     hBox0 = gtk_hbox_new( FALSE, 15 );
96     gtk_widget_set_size_request( hBox0, -1, 80 );
97
98     // start/pause stopwatch button
99     button = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
100                                           HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
101                                           "Start", NULL );
102     button0 = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
103                                            HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
104                                            "Reset", NULL );
105     g_signal_connect( G_OBJECT( button ), "clicked",
106                       G_CALLBACK( start_cb ), button0 );
107     gtk_container_add( GTK_CONTAINER( hBox0 ), button );
108
109     // reset button
110     gtk_widget_set_sensitive( button0, FALSE );
111     g_signal_connect( G_OBJECT( button0 ), "clicked",
112                       G_CALLBACK( reset_cb ), button );
113     gtk_container_add( GTK_CONTAINER( hBox0 ), button0 );
114
115     gtk_box_pack_start( GTK_BOX( vBoxMain ), hBox0, FALSE, FALSE, 0 );
116
117     gtk_container_add( GTK_CONTAINER( window ), vBoxMain );
118
119     gtk_widget_show_all( window );
120
121     return GTK_WINDOW( window );
122 }
123
124
125 void stopish_stopwatch_perf_timer_hour( GtkRadioButton* radio, GtkLabel *label )
126 {
127     stopish_timer_set_precision( TIMER_PRECISION_HOUR );
128     if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
129         stopish_stopwatch_label_timer_landscape(  );
130     else
131         stopish_stopwatch_label_timer_portrait(  );
132 }
133
134
135 void stopish_stopwatch_perf_timer_minute( GtkRadioButton* radio, GtkLabel *label )
136 {
137     stopish_timer_set_precision( TIMER_PRECISION_MINUTE );
138     if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
139         stopish_stopwatch_label_timer_landscape(  );
140     else
141         stopish_stopwatch_label_timer_portrait(  );
142 }
143
144
145 void stopish_stopwatch_label_timer_landscape( void )
146 {
147     gtk_widget_set_size_request( timerdata.vBox, 800, -1 );
148
149     gtk_widget_destroy( timerdata.label );
150     timerdata.label = gtk_label_new( NULL );
151     if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_MINUTE )
152         gtk_label_set_markup( GTK_LABEL( timerdata.label ),
153                               "<span font_family=\"monospace\" "
154                               "size=\"70000\" weight=\"ultrabold\">"
155                               "00:00.0</span>" );
156     else
157         gtk_label_set_markup( GTK_LABEL( timerdata.label ),
158                               "<span font_family=\"monospace\" "
159                               "size=\"70000\" weight=\"ultrabold\">"
160                               "00:00:00.0</span>" );
161     gtk_misc_set_alignment( GTK_MISC( timerdata.label ), 0.5f, 0.5f );
162     gtk_container_add( GTK_CONTAINER( timerdata.vBox ), timerdata.label );
163     gtk_widget_show( timerdata.label );
164 }
165
166
167 void stopish_stopwatch_label_timer_portrait( void )
168 {
169     GtkWidget *vBox, *hBox, *label;
170
171     gtk_widget_set_size_request( timerdata.vBox, 480, -1 );
172
173     gtk_widget_destroy( timerdata.label );
174     vBox = gtk_vbox_new( FALSE, 10 );
175
176     if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR ) {
177         hBox = gtk_hbox_new( FALSE, 10 );
178         label = gtk_label_new( "Hours" );
179         gtk_widget_set_size_request( label, 100, -1 );
180         gtk_misc_set_alignment( GTK_MISC( label ), 1.0f, 0.5f );
181         gtk_container_add( GTK_CONTAINER( hBox ), label );
182         timerdata.labelHour = gtk_label_new( NULL );
183         gtk_widget_set_size_request( timerdata.labelHour, 350, -1 );
184         gtk_misc_set_alignment( GTK_MISC( timerdata.labelHour ), 0.0f, 0.5f );
185         gtk_label_set_markup( GTK_LABEL( timerdata.labelHour ),
186                               "<span font_family=\"monospace\" "
187                               "size=\"80000\" weight=\"ultrabold\">"
188                               "00</span>" );
189         gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelHour );
190         gtk_container_add( GTK_CONTAINER( vBox ), hBox );
191     }
192
193     hBox = gtk_hbox_new( FALSE, 10 );
194     label = gtk_label_new( "Minutes" );
195     gtk_widget_set_size_request( label, 100, -1 );
196     gtk_misc_set_alignment( GTK_MISC( label ), 1.0f, 0.5f );
197     gtk_container_add( GTK_CONTAINER( hBox ), label );
198     timerdata.labelMinute = gtk_label_new( NULL );
199     gtk_widget_set_size_request( timerdata.labelMinute, 350, -1 );
200     gtk_misc_set_alignment( GTK_MISC( timerdata.labelMinute ), 0.0f, 0.5f );
201     gtk_label_set_markup( GTK_LABEL( timerdata.labelMinute ),
202                           "<span font_family=\"monospace\" "
203                           "size=\"80000\" weight=\"ultrabold\">"
204                           "00</span>" );
205     gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelMinute );
206     gtk_container_add( GTK_CONTAINER( vBox ), hBox );
207
208     hBox = gtk_hbox_new( FALSE, 10 );
209     label = gtk_label_new( "Seconds" );
210     gtk_widget_set_size_request( label, 100, -1 );
211     gtk_misc_set_alignment( GTK_MISC( label ), 1.0f, 0.5f );
212     gtk_container_add( GTK_CONTAINER( hBox ), label );
213     timerdata.labelSecond = gtk_label_new( NULL );
214     gtk_widget_set_size_request( timerdata.labelSecond, 350, -1 );
215     gtk_misc_set_alignment( GTK_MISC( timerdata.labelSecond ), 0.0f, 0.5f );
216     gtk_label_set_markup( GTK_LABEL( timerdata.labelSecond ),
217                           "<span font_family=\"monospace\" "
218                           "size=\"80000\" weight=\"ultrabold\">"
219                           "00.0</span>" );
220     gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelSecond );
221     gtk_container_add( GTK_CONTAINER( vBox ), hBox );
222
223     timerdata.label = vBox;
224     gtk_container_add( GTK_CONTAINER( timerdata.vBox ), vBox );
225     gtk_widget_show_all( vBox );
226 }
227
228
229
230 //
231 // Timer callback
232 //
233 static gint timeout_cb( gpointer data )
234 {
235     char formatBuffer[128], tempBuffer[8];
236     char *tempString;
237
238     // print to screen
239     tempString = stopish_get_time_string(  );
240     if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE ) {
241         sprintf( formatBuffer, "<span font_family=\"monospace\" "
242                                "size=\"70000\" weight=\"ultrabold\">"
243                                "%s</span>", tempString );
244         gtk_label_set_markup( GTK_LABEL( timerdata.label ), formatBuffer );
245     }
246     else {
247         if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR ) {
248             sprintf( tempBuffer, "%.2s", tempString );
249             sprintf( formatBuffer, "<span font_family=\"monospace\" "
250                                    "size=\"80000\" weight=\"ultrabold\">"
251                                    "%s</span>", tempBuffer );
252             gtk_label_set_markup( GTK_LABEL( timerdata.labelHour ),
253                                   formatBuffer );
254         }
255         if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR )
256             sprintf( tempBuffer, "%.2s", tempString + 3 );
257         else
258             sprintf( tempBuffer, "%.2s", tempString );
259         sprintf( formatBuffer, "<span font_family=\"monospace\" "
260                                "size=\"80000\" weight=\"ultrabold\">"
261                                "%s</span>", tempBuffer );
262         gtk_label_set_markup( GTK_LABEL( timerdata.labelMinute ),
263                               formatBuffer );
264         if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR )
265             sprintf( tempBuffer, "%.4s", tempString + 6 );
266         else
267             sprintf( tempBuffer, "%.4s", tempString + 3 );
268         sprintf( formatBuffer, "<span font_family=\"monospace\" "
269                                "size=\"80000\" weight=\"ultrabold\">"
270                                "%s</span>", tempBuffer );
271         gtk_label_set_markup( GTK_LABEL( timerdata.labelSecond ),
272                               formatBuffer );
273     }
274     free( tempString );
275
276     return TRUE;
277 }
278
279
280 static void start_cb( GtkButton* button, gpointer data )
281 {
282     if ( stopish_get_mode(  ) == STOPISH_MODE_START ) {
283         // set label text and add timer handle
284         gtk_button_set_label( button, "Pause" );
285         stopish_set_mode( STOPISH_MODE_PAUSE );
286         stopish_set_time_start( stopish_current_time(  ) );
287         timerHandle = g_timeout_add( 100, timeout_cb, NULL );
288     }
289     else if ( stopish_get_mode(  ) == STOPISH_MODE_RESUME ) {
290         // resume timer
291         gtk_button_set_label( button, "Pause" );
292         stopish_set_mode( STOPISH_MODE_PAUSE );
293         stopish_timer_resume(  );
294         timerHandle = g_timeout_add( 100, timeout_cb, NULL );
295     }
296     else {
297         // pause timer, remove timeout
298         gtk_button_set_label( button, "Resume" );
299         stopish_set_mode( STOPISH_MODE_RESUME );
300         g_source_remove( timerHandle );
301         stopish_timer_save(  );
302     }
303
304     // allow user to reset timer
305     gtk_widget_set_sensitive( GTK_WIDGET( data ), TRUE );
306 }
307
308
309 static void reset_cb( GtkButton* button, gpointer data )
310 {
311     GSList *tempList;
312     char *tempString;
313     char formatString[128];
314
315     if ( stopish_get_mode(  ) == STOPISH_MODE_RESUME )
316         stopish_timer_resume(  );
317
318     // set label text and remove timer handle
319     gtk_button_set_label( GTK_BUTTON( data ), "Start" );
320     stopish_set_mode( STOPISH_MODE_START );
321     if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_MINUTE )
322         gtk_label_set_markup( GTK_LABEL( timerdata.label ),
323                               "<span font_family=\"monospace\" "
324                               "size=\"70000\" weight=\"ultrabold\">"
325                               "00:00.0</span>" );
326     else
327         gtk_label_set_markup( GTK_LABEL( timerdata.label ),
328                               "<span font_family=\"monospace\" "
329                               "size=\"70000\" weight=\"ultrabold\">"
330                               "00:00:00.0</span>" );
331     g_source_remove( timerHandle );
332
333     // add current time to history
334     historyList = g_slist_prepend( historyList,
335                                    ( gpointer ) stopish_get_time_string(  ) );
336     sprintf( formatString, "<span size=\"large\">%s</span>",
337              ( char * ) historyList->data );
338     gtk_label_set_markup( GTK_LABEL( timerHistoryLabel1 ),
339                           formatString );
340     tempList = historyList;
341     tempList = g_slist_next( tempList );
342     if ( tempList ) {
343         gtk_label_set_text( GTK_LABEL( timerHistoryLabel2 ),
344                             ( char * ) tempList->data );
345     }
346     tempList = g_slist_next( tempList );
347     if ( tempList ) {
348         sprintf( formatString, "<span size=\"small\">%s</span>",
349                  ( char * ) tempList->data );
350         gtk_label_set_markup( GTK_LABEL( timerHistoryLabel3 ),
351                               formatString );
352     }
353     tempList = g_slist_next( tempList );
354     if ( tempList ) {
355         sprintf( formatString, "<span size=\"x-small\">%s</span>",
356                  ( char * ) tempList->data );
357         gtk_label_set_markup( GTK_LABEL( timerHistoryLabel4 ),
358                               formatString );
359     }
360
361     // remove the history time after the 4th
362     tempList = g_slist_next( tempList );
363     if ( tempList ) {
364         tempString = tempList->data;
365         historyList = g_slist_remove( historyList, tempList->data );
366         free( tempString );
367     }
368
369     // reset start time
370     stopish_set_time_start( 0 );
371
372     // disallow user to reset timer
373     gtk_widget_set_sensitive( GTK_WIDGET( button ), FALSE );
374 }