Add 4th line of history. Gradually shrink history font size.
[stopish] / src / stopish.c
1 //      stopish.c
2 //
3 //      Copyright 2009 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 <string.h>
21 #include <stdlib.h>
22 #include <sys/time.h>
23 #include <gtk/gtk.h>
24 #include <libosso.h>
25
26 #include "stopish.h"
27
28 static GtkWidget *timerLabel = NULL;
29 static GtkWidget *timerHistoryLabel1 = NULL;
30 static GtkWidget *timerHistoryLabel2 = NULL;
31 static GtkWidget *timerHistoryLabel3 = NULL;
32 static GtkWidget *timerHistoryLabel4 = NULL;
33 static GSList *historyList = NULL;
34 static int stopishMode = STOPISH_MODE_START;
35 static int timerHandle = -1;
36
37 //Prototypes
38 gint dbus_callback( const gchar *interface, const gchar *method,
39                         GArray *arguments, gpointer data, osso_rpc_t *retval );
40 static GtkWindow *stopish_new( void );
41 static void start_cb( GtkButton* button, gpointer data );
42 static void reset_cb( GtkButton* button, gpointer data );
43 static void close_cb( GtkButton* button, gpointer data );
44
45
46 int main( int argc, char *argv[] )
47 {
48     osso_context_t *ctxt;
49     osso_return_t ret;
50     GtkWindow *window;
51
52     //printf( "stopish: starting up\n" );
53
54     ctxt = osso_initialize( "com.nokia.stopish", PACKAGE_VERSION, TRUE, NULL );
55     if ( ctxt == NULL ) {
56         fprintf( stderr, "osso_initialize failed.\n" );
57         exit( 1 );
58     }
59
60     gtk_init( &argc, &argv );
61
62     window = stopish_new(  );
63
64     ret = osso_rpc_set_default_cb_f( ctxt, dbus_callback, window );
65     if ( ret != OSSO_OK ) {
66         fprintf( stderr, "osso_rpc_set_default_cb_f failed: %d.\n", ret );
67         exit( 1 );
68     }
69
70     gtk_main(  );
71
72     return 0;
73 }
74
75
76 gint dbus_callback( const gchar *interface, const gchar *method,
77                     GArray *arguments, gpointer data, osso_rpc_t *retval )
78 {
79     //printf( "stopish dbus: %s, %s\n", interface, method );
80
81     if ( !strcmp( method, "top_application" ) )
82         gtk_window_present( GTK_WINDOW( data ) );
83
84     retval->type = DBUS_TYPE_INVALID;
85
86     return OSSO_OK;
87 }
88
89
90 int stopish_get_mode( void )
91 {
92     return stopishMode;
93 }
94
95
96 static GtkWindow *stopish_new( void )
97 {
98     GtkWidget *window, *hBox, *label, *button, *button0;
99     GtkWidget *vBox, *vBox0, *vBox1;
100
101     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
102
103     gtk_container_set_border_width( GTK_CONTAINER( window ), 20 );
104
105     gtk_window_set_title( GTK_WINDOW( window ), "Stopish" );
106
107     g_signal_connect( G_OBJECT( window ), "destroy",
108                       G_CALLBACK( close_cb ), window );
109
110     vBox = gtk_vbox_new( FALSE, 20 );
111
112     label = gtk_label_new( "Stopish - The Stopwatch" );
113     gtk_box_pack_start( GTK_BOX( vBox ), label, FALSE, FALSE, 0 );
114
115     hBox = gtk_hbox_new( FALSE, 10 );
116
117     // stop watch area
118     vBox0 = gtk_vbox_new( FALSE, 5 );
119     gtk_widget_set_size_request( vBox0, 250, -1 );
120
121     // main timer
122     timerLabel = gtk_label_new( NULL );
123     gtk_widget_set_size_request( timerLabel, -1, 150 );
124     gtk_label_set_markup( GTK_LABEL( timerLabel ),
125                           "<span font_family=\"monospace\" size=\"xx-large\">00:00:00.0</span>" );
126     gtk_box_pack_start( GTK_BOX( vBox0 ), timerLabel, FALSE, FALSE, 0 );
127
128     // history area
129     timerHistoryLabel1 = gtk_label_new( NULL );
130     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel1, FALSE, FALSE, 0 );
131     timerHistoryLabel2 = gtk_label_new( NULL );
132     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel2, FALSE, FALSE, 0 );
133     timerHistoryLabel3 = gtk_label_new( NULL );
134     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel3, FALSE, FALSE, 0 );
135     timerHistoryLabel4 = gtk_label_new( NULL );
136     gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel4, FALSE, FALSE, 0 );
137     label = gtk_label_new( NULL );
138     gtk_container_add( GTK_CONTAINER( vBox0 ), label );
139
140     gtk_container_add( GTK_CONTAINER( hBox ), vBox0 );
141
142     // button area
143     vBox1 = gtk_vbox_new( FALSE, 15 );
144     gtk_widget_set_size_request( vBox1, 200, -1 );
145
146     // start/pause stopwatch button
147     button = gtk_button_new_with_label( "Start" );
148     button0 = gtk_button_new_with_label( "Reset" );
149     gtk_widget_set_size_request( button, -1, 60 );
150     g_signal_connect( G_OBJECT( button ), "clicked",
151                       G_CALLBACK( start_cb ), button0 );
152     gtk_box_pack_start( GTK_BOX( vBox1 ), button, FALSE, FALSE, 0 );
153
154     // reset button
155     gtk_widget_set_sensitive( button0, FALSE );
156     gtk_widget_set_size_request( button0, -1, 60 );
157     g_signal_connect( G_OBJECT( button0 ), "clicked",
158                       G_CALLBACK( reset_cb ), button );
159     gtk_box_pack_start( GTK_BOX( vBox1 ), button0, FALSE, FALSE, 0 );
160
161     gtk_container_add( GTK_CONTAINER( hBox ), vBox1 );
162
163     gtk_container_add( GTK_CONTAINER( vBox ), hBox );
164
165     gtk_container_add( GTK_CONTAINER( window ), vBox );
166
167     gtk_widget_show_all( window );
168
169     return GTK_WINDOW( window );
170 }
171
172
173 static void start_cb( GtkButton* button, gpointer data )
174 {
175     if ( stopishMode == STOPISH_MODE_START ) {
176         // set label text and add timer handle
177         gtk_button_set_label( button, "Pause" );
178         stopishMode = STOPISH_MODE_PAUSE;
179         stopish_set_time_start( stopish_current_time(  ) );
180         timerHandle = g_timeout_add( 100, stopish_timeout_cb, timerLabel );
181     }
182     else if ( stopishMode == STOPISH_MODE_RESUME ) {
183         // resume timer
184         gtk_button_set_label( button, "Pause" );
185         stopishMode = STOPISH_MODE_PAUSE;
186         stopish_timer_resume(  );
187         timerHandle = g_timeout_add( 100, stopish_timeout_cb, timerLabel );
188     }
189     else {
190         // pause timer, remove timeout
191         gtk_button_set_label( button, "Resume" );
192         stopishMode = STOPISH_MODE_RESUME;
193         g_source_remove( timerHandle );
194         stopish_timer_save(  );
195     }
196
197     // allow user to reset timer
198     gtk_widget_set_sensitive( GTK_WIDGET( data ), TRUE );
199 }
200
201
202 static void reset_cb( GtkButton* button, gpointer data )
203 {
204     GSList *tempList;
205     char *tempString;
206     char formatString[64];
207
208     if ( stopishMode == STOPISH_MODE_RESUME )
209         stopish_timer_resume(  );
210
211     // set label text and remove timer handle
212     gtk_button_set_label( GTK_BUTTON( data ), "Start" );
213     stopishMode = STOPISH_MODE_START;
214     gtk_label_set_markup( GTK_LABEL( timerLabel ),
215                           "<span font_family=\"monospace\" size=\"xx-large\">00:00:00.0</span>" );
216     g_source_remove( timerHandle );
217
218     // add current time to history
219     historyList = g_slist_prepend( historyList,
220                                    ( gpointer ) stopish_get_time_string(  ) );
221     gtk_label_set_text( GTK_LABEL( timerHistoryLabel1 ),
222                         ( char * ) historyList->data );
223     tempList = historyList;
224     tempList = g_slist_next( tempList );
225     if ( tempList ) {
226         sprintf( formatString, "<span size=\"small\">%s</span>",
227                  ( char * ) tempList->data );
228         gtk_label_set_markup( GTK_LABEL( timerHistoryLabel2 ),
229                               formatString );
230     }
231     tempList = g_slist_next( tempList );
232     if ( tempList ) {
233         sprintf( formatString, "<span size=\"x-small\">%s</span>",
234                  ( char * ) tempList->data );
235         gtk_label_set_markup( GTK_LABEL( timerHistoryLabel3 ),
236                               formatString );
237     }
238     tempList = g_slist_next( tempList );
239     if ( tempList ) {
240         sprintf( formatString, "<span size=\"xx-small\">%s</span>",
241                  ( char * ) tempList->data );
242         gtk_label_set_markup( GTK_LABEL( timerHistoryLabel4 ),
243                               formatString );
244     }
245
246     // remove the history time after the 4th
247     tempList = g_slist_next( tempList );
248     if ( tempList ) {
249         tempString = tempList->data;
250         historyList = g_slist_remove( historyList, tempList->data );
251         free( tempString );
252     }
253
254     // reset start time
255     stopish_set_time_start( 0 );
256
257     // disallow user to reset timer
258     gtk_widget_set_sensitive( GTK_WIDGET( button ), FALSE );
259 }
260
261
262 static void close_cb( GtkButton* button, gpointer data )
263 {
264     // destroy main window and exit gtk main loop
265     gtk_widget_destroy( GTK_WIDGET( data ) );
266     gtk_main_quit(  );
267 }