Add countdown functionality with same modes as the
authorMichael Cronenworth <michael@melchior.(none)>
Fri, 19 Feb 2010 19:27:30 +0000 (13:27 -0600)
committerMichael Cronenworth <michael@melchior.(none)>
Fri, 19 Feb 2010 19:27:30 +0000 (13:27 -0600)
stopwatch. Also, add about dialog.

src/Makefile.am
src/stopish-countdown.c [new file with mode: 0644]
src/stopish-stopwatch.c
src/stopish.c
src/stopish.h
src/timer.c

index 3b3cdeb..06845f2 100644 (file)
@@ -8,7 +8,8 @@
 
 bin_PROGRAMS = stopish
 
-stopish_SOURCES = stopish.c stopish.h stopish-stopwatch.c timer.c
+stopish_SOURCES = stopish.c stopish.h stopish-countdown.c \
+                  stopish-stopwatch.c timer.c
 
 stopish_CFLAGS = $(GTK_CFLAGS) $(OSSO_CFLAGS) $(DESKTOP_CFLAGS) \
                                 $(DBUS_CFLAGS) $(MCE_CFLAGS)
diff --git a/src/stopish-countdown.c b/src/stopish-countdown.c
new file mode 100644 (file)
index 0000000..90514b9
--- /dev/null
@@ -0,0 +1,457 @@
+//      stopish-countdown.c
+//
+//      Copyright 2010 Michael Cronenworth <mike@cchtml.com>
+//
+//      This program is free software; you can redistribute it and/or modify
+//      it under the terms of the GNU General Public License as published by
+//      the Free Software Foundation; either version 2 of the License, or
+//      (at your option) any later version.
+//
+//      This program is distributed in the hope that it will be useful,
+//      but WITHOUT ANY WARRANTY; without even the implied warranty of
+//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//      GNU General Public License for more details.
+//
+//      You should have received a copy of the GNU General Public License
+//      along with this program; if not, write to the Free Software
+//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+//      MA 02110-1301, USA.
+
+#include <gtk/gtk.h>
+#include <hildon/hildon.h>
+#include <stdlib.h>
+
+#include "stopish.h"
+
+struct timerData {
+    GtkWidget *vBox;
+    GtkWidget *label;
+    GtkWidget *labelHour;
+    GtkWidget *labelMinute;
+    GtkWidget *labelSecond;
+};
+
+static struct timerData timerdata;
+static int timerHandle = -1;
+static GtkWidget *window = NULL;
+static GtkWidget *resetButton;
+static int startMinutes = 0;
+static int startSeconds = 0;
+
+//Prototypes
+static void main_menu( GtkWindow *window );
+static void close_cb( void );
+static void countdown_perf_timer_hour( GtkRadioButton* radio, GtkLabel *label );
+static void countdown_perf_timer_minute( GtkRadioButton* radio, GtkLabel *label );
+static gint timeout_cb( gpointer data );
+static void start_cb( GtkButton* button, gpointer data );
+static void reset_cb( GtkButton* button, gpointer data );
+static void set_cb( GtkButton* button, gpointer data );
+
+
+void stopish_countdown_new( void )
+{
+    GtkWidget *button, *label;
+    GtkWidget *vBoxMain, *vBox0, *hBox0;
+
+    window = hildon_stackable_window_new(  );
+
+    gtk_container_set_border_width( GTK_CONTAINER( window ), 20 );
+
+    gtk_window_set_title( GTK_WINDOW( window ), "Stopish" );
+
+    // attach signals to main window
+    g_signal_connect( G_OBJECT( window ), "destroy",
+                      G_CALLBACK( close_cb ), NULL );
+    g_signal_connect( G_OBJECT( window ), "focus-in-event",
+                      G_CALLBACK( stopish_focus_in_cb ), NULL );
+    g_signal_connect( G_OBJECT( window ), "focus-out-event",
+                      G_CALLBACK( stopish_focus_out_cb ), NULL );
+
+    // initialize menu
+    main_menu( GTK_WINDOW( window ) );
+
+    vBoxMain = gtk_vbox_new( FALSE, 10 );
+
+    // separator
+    label = gtk_label_new( NULL );
+    gtk_container_add( GTK_CONTAINER( vBoxMain ), label );
+
+    vBox0 = gtk_vbox_new( FALSE, 5 );
+
+    // countdown area
+    timerdata.vBox = gtk_vbox_new( FALSE, 0 );
+    gtk_container_add( GTK_CONTAINER( vBox0 ), timerdata.vBox );
+    gtk_container_add( GTK_CONTAINER( vBoxMain ), vBox0 );
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
+        stopish_countdown_label_timer_landscape(  );
+    else
+        stopish_countdown_label_timer_portrait(  );
+
+    // separator
+    label = gtk_label_new( NULL );
+    gtk_container_add( GTK_CONTAINER( vBoxMain ), label );
+
+    // button area
+    hBox0 = gtk_hbox_new( FALSE, 15 );
+    gtk_widget_set_size_request( hBox0, -1, 80 );
+
+    // start/pause countdown button
+    button = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
+                                          HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                          "Start", NULL );
+    resetButton = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
+                                               HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                              "Reset", NULL );
+    g_signal_connect( G_OBJECT( button ), "clicked",
+                      G_CALLBACK( start_cb ), resetButton );
+    gtk_container_add( GTK_CONTAINER( hBox0 ), button );
+
+    // reset button
+    gtk_widget_set_sensitive( resetButton, FALSE );
+    g_signal_connect( G_OBJECT( resetButton ), "clicked",
+                      G_CALLBACK( reset_cb ), button );
+    gtk_container_add( GTK_CONTAINER( hBox0 ), resetButton );
+
+    // set button
+    button = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
+                                          HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                          "Set", NULL );
+    g_signal_connect( G_OBJECT( button ), "clicked",
+                      G_CALLBACK( set_cb ), button );
+    gtk_container_add( GTK_CONTAINER( hBox0 ), button );
+
+
+    gtk_box_pack_start( GTK_BOX( vBoxMain ), hBox0, FALSE, FALSE, 0 );
+    gtk_container_add( GTK_CONTAINER( window ), vBoxMain );
+
+    gtk_widget_show_all( window );
+}
+
+
+void stopish_countdown_label_timer_landscape( void )
+{
+    gtk_widget_set_size_request( timerdata.vBox, 800, -1 );
+
+    gtk_widget_destroy( timerdata.label );
+    timerdata.label = gtk_label_new( NULL );
+    if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_MINUTE )
+        gtk_label_set_markup( GTK_LABEL( timerdata.label ),
+                              "<span font_family=\"monospace\" "
+                              "size=\"80000\" weight=\"ultrabold\">"
+                              "00:00.0</span>" );
+    else
+        gtk_label_set_markup( GTK_LABEL( timerdata.label ),
+                              "<span font_family=\"monospace\" "
+                              "size=\"80000\" weight=\"ultrabold\">"
+                              "00:00:00.0</span>" );
+    gtk_misc_set_alignment( GTK_MISC( timerdata.label ), 0.5f, 0.5f );
+    gtk_container_add( GTK_CONTAINER( timerdata.vBox ), timerdata.label );
+    gtk_widget_show( timerdata.label );
+}
+
+
+void stopish_countdown_label_timer_portrait( void )
+{
+    GtkWidget *vBox, *hBox, *label;
+
+    gtk_widget_set_size_request( timerdata.vBox, 480, -1 );
+
+    gtk_widget_destroy( timerdata.label );
+    vBox = gtk_vbox_new( FALSE, 10 );
+
+    if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR ) {
+        hBox = gtk_hbox_new( FALSE, 10 );
+        label = gtk_label_new( "Hours" );
+        gtk_widget_set_size_request( label, 100, -1 );
+        gtk_misc_set_alignment( GTK_MISC( label ), 1.0f, 0.5f );
+        gtk_container_add( GTK_CONTAINER( hBox ), label );
+        timerdata.labelHour = gtk_label_new( NULL );
+        gtk_widget_set_size_request( timerdata.labelHour, 350, -1 );
+        gtk_misc_set_alignment( GTK_MISC( timerdata.labelHour ), 0.0f, 0.5f );
+        gtk_label_set_markup( GTK_LABEL( timerdata.labelHour ),
+                              "<span font_family=\"monospace\" "
+                              "size=\"90000\" weight=\"ultrabold\">"
+                              "00</span>" );
+        gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelHour );
+        gtk_container_add( GTK_CONTAINER( vBox ), hBox );
+    }
+
+    hBox = gtk_hbox_new( FALSE, 10 );
+    label = gtk_label_new( "Minutes" );
+    gtk_widget_set_size_request( label, 100, -1 );
+    gtk_misc_set_alignment( GTK_MISC( label ), 1.0f, 0.5f );
+    gtk_container_add( GTK_CONTAINER( hBox ), label );
+    timerdata.labelMinute = gtk_label_new( NULL );
+    gtk_widget_set_size_request( timerdata.labelMinute, 350, -1 );
+    gtk_misc_set_alignment( GTK_MISC( timerdata.labelMinute ), 0.0f, 0.5f );
+    gtk_label_set_markup( GTK_LABEL( timerdata.labelMinute ),
+                          "<span font_family=\"monospace\" "
+                          "size=\"90000\" weight=\"ultrabold\">"
+                          "00</span>" );
+    gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelMinute );
+    gtk_container_add( GTK_CONTAINER( vBox ), hBox );
+
+    hBox = gtk_hbox_new( FALSE, 10 );
+    label = gtk_label_new( "Seconds" );
+    gtk_widget_set_size_request( label, 100, -1 );
+    gtk_misc_set_alignment( GTK_MISC( label ), 1.0f, 0.5f );
+    gtk_container_add( GTK_CONTAINER( hBox ), label );
+    timerdata.labelSecond = gtk_label_new( NULL );
+    gtk_widget_set_size_request( timerdata.labelSecond, 350, -1 );
+    gtk_misc_set_alignment( GTK_MISC( timerdata.labelSecond ), 0.0f, 0.5f );
+    gtk_label_set_markup( GTK_LABEL( timerdata.labelSecond ),
+                          "<span font_family=\"monospace\" "
+                          "size=\"90000\" weight=\"ultrabold\">"
+                          "00.0</span>" );
+    gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelSecond );
+    gtk_container_add( GTK_CONTAINER( vBox ), hBox );
+
+    timerdata.label = vBox;
+    gtk_container_add( GTK_CONTAINER( timerdata.vBox ), vBox );
+    gtk_widget_show_all( vBox );
+}
+
+
+static void main_menu( GtkWindow *window )
+{
+    HildonAppMenu *menu;
+    GtkWidget *button, *radio;
+
+    menu = ( HildonAppMenu * ) hildon_app_menu_new(  );
+
+    button = gtk_button_new_with_label( "About" );
+    g_signal_connect_after( G_OBJECT( button ), "clicked",
+                            G_CALLBACK( stopish_about_cb ),
+                            STOPISH_TYPE_STOPWATCH );
+    hildon_app_menu_append( menu, GTK_BUTTON( button ) );
+
+    // Hour preference
+    radio = gtk_radio_button_new_with_label( NULL, "Hour" );
+    gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON( radio ), FALSE );
+    g_signal_connect_after( G_OBJECT( radio ), "clicked",
+                            G_CALLBACK( countdown_perf_timer_hour ), NULL );
+    hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
+
+    // Minute preference
+    radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON( radio ), "Minute" );
+    gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON ( radio ), FALSE );
+    g_signal_connect_after( G_OBJECT( radio ), "clicked",
+                            G_CALLBACK( countdown_perf_timer_minute ), NULL );
+    hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
+
+    // default to minute
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radio ), TRUE );
+
+    gtk_widget_show_all( GTK_WIDGET( menu ) );
+
+    hildon_window_set_app_menu( HILDON_WINDOW( window ), menu );
+}
+
+
+static void close_cb( void )
+{
+    gtk_widget_destroy( window );
+    if ( timerHandle != -1 &&
+         stopish_get_mode(  ) != STOPISH_MODE_RESUME )
+        gtk_button_clicked( GTK_BUTTON( resetButton ) );
+    startMinutes = startSeconds = 0;
+    stopish_set_type( STOPISH_TYPE_STOPWATCH );
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
+        stopish_stopwatch_label_timer_landscape(  );
+    else
+        stopish_stopwatch_label_timer_portrait(  );
+}
+
+
+static void countdown_perf_timer_hour( GtkRadioButton* radio, GtkLabel *label )
+{
+    stopish_timer_set_precision( TIMER_PRECISION_HOUR );
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
+        stopish_countdown_label_timer_landscape(  );
+    else
+        stopish_countdown_label_timer_portrait(  );
+}
+
+
+static void countdown_perf_timer_minute( GtkRadioButton* radio, GtkLabel *label )
+{
+    stopish_timer_set_precision( TIMER_PRECISION_MINUTE );
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
+        stopish_countdown_label_timer_landscape(  );
+    else
+        stopish_countdown_label_timer_portrait(  );
+}
+
+
+//
+// Timer callback
+//
+static gint timeout_cb( gpointer data )
+{
+    char formatBuffer[128], tempBuffer[8];
+    char *tempString;
+
+    // print to screen
+    tempString = stopish_get_time_string(  );
+    if ( tempString == NULL ) {
+        gtk_button_clicked( GTK_BUTTON( resetButton ) );
+        return FALSE;
+    }
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE ) {
+        sprintf( formatBuffer, "<span font_family=\"monospace\" "
+                               "size=\"80000\" weight=\"ultrabold\">"
+                               "%s</span>", tempString );
+        gtk_label_set_markup( GTK_LABEL( timerdata.label ), formatBuffer );
+    }
+    else {
+        if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR ) {
+            sprintf( tempBuffer, "%.2s", tempString );
+            sprintf( formatBuffer, "<span font_family=\"monospace\" "
+                                   "size=\"90000\" weight=\"ultrabold\">"
+                                   "%s</span>", tempBuffer );
+            gtk_label_set_markup( GTK_LABEL( timerdata.labelHour ),
+                                  formatBuffer );
+        }
+        if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR )
+            sprintf( tempBuffer, "%.2s", tempString + 3 );
+        else
+            sprintf( tempBuffer, "%.2s", tempString );
+        sprintf( formatBuffer, "<span font_family=\"monospace\" "
+                               "size=\"90000\" weight=\"ultrabold\">"
+                               "%s</span>", tempBuffer );
+        gtk_label_set_markup( GTK_LABEL( timerdata.labelMinute ),
+                              formatBuffer );
+        if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR )
+            sprintf( tempBuffer, "%.4s", tempString + 6 );
+        else
+            sprintf( tempBuffer, "%.4s", tempString + 3 );
+        sprintf( formatBuffer, "<span font_family=\"monospace\" "
+                               "size=\"90000\" weight=\"ultrabold\">"
+                               "%s</span>", tempBuffer );
+        gtk_label_set_markup( GTK_LABEL( timerdata.labelSecond ),
+                              formatBuffer );
+    }
+    free( tempString );
+
+    return TRUE;
+}
+
+
+static void start_cb( GtkButton* button, gpointer data )
+{
+    long int offset;
+
+    if ( stopish_get_mode(  ) == STOPISH_MODE_START ) {
+        // set label text and add timer handle
+        offset = ( startMinutes * 600 ) + ( startSeconds * 10 );
+        if ( offset <= 0 )
+            return;
+        gtk_button_set_label( button, "Pause" );
+        stopish_set_mode( STOPISH_MODE_PAUSE );
+        stopish_set_time_start( stopish_current_time(  ) + offset );
+        timerHandle = g_timeout_add( 100, timeout_cb, NULL );
+    }
+    else if ( stopish_get_mode(  ) == STOPISH_MODE_RESUME ) {
+        // resume timer
+        gtk_button_set_label( button, "Pause" );
+        stopish_set_mode( STOPISH_MODE_PAUSE );
+        stopish_timer_resume(  );
+        timerHandle = g_timeout_add( 100, timeout_cb, NULL );
+    }
+    else {
+        // pause timer, remove timeout
+        gtk_button_set_label( button, "Resume" );
+        stopish_set_mode( STOPISH_MODE_RESUME );
+        g_source_remove( timerHandle );
+        timerHandle = -1;
+        stopish_timer_save(  );
+    }
+
+    // allow user to reset timer
+    gtk_widget_set_sensitive( GTK_WIDGET( data ), TRUE );
+}
+
+
+static void reset_cb( GtkButton* button, gpointer data )
+{
+    if ( stopish_get_mode(  ) == STOPISH_MODE_RESUME )
+        stopish_timer_resume(  );
+
+    // set label text and remove timer handle
+    gtk_button_set_label( GTK_BUTTON( data ), "Start" );
+    stopish_set_mode( STOPISH_MODE_START );
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
+        stopish_countdown_label_timer_landscape(  );
+    else
+        stopish_countdown_label_timer_portrait(  );
+    g_source_remove( timerHandle );
+    timerHandle = -1;
+
+    // reset start time
+    stopish_set_time_start( 0 );
+
+    // disallow user to reset timer
+    gtk_widget_set_sensitive( GTK_WIDGET( button ), FALSE );
+}
+
+
+static void set_cb( GtkButton* button, gpointer data )
+{
+    GtkWidget *picker;
+    GtkWidget *selector;
+    GtkListStore *minutes, *seconds;
+    GtkTreeIter iter;
+    HildonTouchSelectorColumn *column = NULL;
+    int i, ret;
+
+    // create popup window for setting start time
+    picker = hildon_picker_dialog_new( GTK_WINDOW( window ) );
+    gtk_window_set_title( GTK_WINDOW( picker ), "Set Timer Start" );
+
+    selector = hildon_touch_selector_new(  );
+
+    minutes = gtk_list_store_new( 1, G_TYPE_INT );
+    for ( i = 0; i < 60; ++i ) {
+        gtk_list_store_append( minutes, &iter );
+        gtk_list_store_set( minutes, &iter, 0, i, -1 );
+    }
+
+    seconds = gtk_list_store_new( 1, G_TYPE_INT );
+    for ( i = 0; i < 60; ++i ) {
+        gtk_list_store_append( seconds, &iter );
+        gtk_list_store_set( seconds, &iter, 0, i, -1 );
+    }
+
+    column = hildon_touch_selector_append_text_column( HILDON_TOUCH_SELECTOR( selector ),
+                                                  GTK_TREE_MODEL( minutes ),
+                                                  TRUE );
+    hildon_touch_selector_column_set_text_column( column, 0 );
+    g_object_unref( minutes );
+
+    column = hildon_touch_selector_append_text_column( HILDON_TOUCH_SELECTOR( selector ),
+                                                  GTK_TREE_MODEL( seconds ),
+                                                  TRUE );
+    hildon_touch_selector_column_set_text_column( column, 0 );
+    g_object_unref( seconds );
+
+    hildon_picker_dialog_set_selector( HILDON_PICKER_DIALOG( picker ),
+                                       HILDON_TOUCH_SELECTOR( selector ) );
+
+    ret = gtk_dialog_run( GTK_DIALOG( picker ) );
+
+    // evaluate dialog response
+    switch ( ret ) {
+        case GTK_RESPONSE_OK:
+            startMinutes =
+                hildon_touch_selector_get_active( HILDON_TOUCH_SELECTOR( selector ),
+                                                  0 );
+            startSeconds =
+                hildon_touch_selector_get_active( HILDON_TOUCH_SELECTOR( selector ),
+                                                  1 );
+            break;
+        default:
+            break;
+    }
+    gtk_widget_destroy( GTK_WIDGET( picker ) );
+}
index 5129c8d..02f19b7 100644 (file)
@@ -32,10 +32,8 @@ struct timerData {
 };
 
 static struct timerData timerdata;
-static GtkWidget *timerHistoryLabel1 = NULL;
-static GtkWidget *timerHistoryLabel2 = NULL;
-static GtkWidget *timerHistoryLabel3 = NULL;
-static GtkWidget *timerHistoryLabel4 = NULL;
+static GtkWidget *timerHistoryLabel[4];
+static GtkWidget *resetButton;
 static GSList *historyList = NULL;
 static int timerHandle = -1;
 
@@ -47,7 +45,7 @@ static void reset_cb( GtkButton* button, gpointer data );
 
 GtkWindow *stopish_stopwatch_new( void )
 {
-    GtkWidget *window, *button, *button0, *label;
+    GtkWidget *window, *button, *label;
     GtkWidget *vBoxMain, *vBox0, *hBox0;
 
     window = hildon_stackable_window_new(  );
@@ -70,20 +68,20 @@ GtkWindow *stopish_stopwatch_new( void )
     stopish_stopwatch_label_timer_landscape(  );
 
     // history area
-    timerHistoryLabel1 = gtk_label_new( NULL );
-    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel1 ),
+    timerHistoryLabel[0] = gtk_label_new( NULL );
+    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel[0] ),
                           "<span size=\"large\"> </span>" );
-    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel1, FALSE, FALSE, 0 );
-    timerHistoryLabel2 = gtk_label_new( NULL );
-    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel2, FALSE, FALSE, 0 );
-    timerHistoryLabel3 = gtk_label_new( NULL );
-    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel3 ),
+    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel[0], FALSE, FALSE, 0 );
+    timerHistoryLabel[1] = gtk_label_new( NULL );
+    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel[1], FALSE, FALSE, 0 );
+    timerHistoryLabel[2] = gtk_label_new( NULL );
+    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel[2] ),
                           "<span size=\"small\"> </span>" );
-    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel3, FALSE, FALSE, 0 );
-    timerHistoryLabel4 = gtk_label_new( NULL );
-    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel4 ),
+    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel[2], FALSE, FALSE, 0 );
+    timerHistoryLabel[3] = gtk_label_new( NULL );
+    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel[3] ),
                           "<span size=\"x-small\"> </span>" );
-    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel4, FALSE, FALSE, 0 );
+    gtk_box_pack_start( GTK_BOX( vBox0 ), timerHistoryLabel[3], FALSE, FALSE, 0 );
 
     gtk_container_add( GTK_CONTAINER( vBoxMain ), vBox0 );
 
@@ -99,18 +97,18 @@ GtkWindow *stopish_stopwatch_new( void )
     button = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
                                           HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
                                           "Start", NULL );
-    button0 = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
-                                           HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
-                                           "Reset", NULL );
+    resetButton = hildon_button_new_with_text( HILDON_SIZE_HALFSCREEN_WIDTH,
+                                               HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                               "Reset", NULL );
     g_signal_connect( G_OBJECT( button ), "clicked",
-                      G_CALLBACK( start_cb ), button0 );
+                      G_CALLBACK( start_cb ), resetButton );
     gtk_container_add( GTK_CONTAINER( hBox0 ), button );
 
     // reset button
-    gtk_widget_set_sensitive( button0, FALSE );
-    g_signal_connect( G_OBJECT( button0 ), "clicked",
+    gtk_widget_set_sensitive( resetButton, FALSE );
+    g_signal_connect( G_OBJECT( resetButton ), "clicked",
                       G_CALLBACK( reset_cb ), button );
-    gtk_container_add( GTK_CONTAINER( hBox0 ), button0 );
+    gtk_container_add( GTK_CONTAINER( hBox0 ), resetButton );
 
     gtk_box_pack_start( GTK_BOX( vBoxMain ), hBox0, FALSE, FALSE, 0 );
 
@@ -122,6 +120,15 @@ GtkWindow *stopish_stopwatch_new( void )
 }
 
 
+void stopish_stopwatch_reset( void )
+{
+    if ( timerHandle == -1 &&
+         stopish_get_mode(  ) != STOPISH_MODE_RESUME )
+        return;
+    gtk_button_clicked( GTK_BUTTON( resetButton ) );
+}
+
+
 void stopish_stopwatch_perf_timer_hour( GtkRadioButton* radio, GtkLabel *label )
 {
     stopish_timer_set_precision( TIMER_PRECISION_HOUR );
@@ -151,12 +158,12 @@ void stopish_stopwatch_label_timer_landscape( void )
     if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_MINUTE )
         gtk_label_set_markup( GTK_LABEL( timerdata.label ),
                               "<span font_family=\"monospace\" "
-                              "size=\"70000\" weight=\"ultrabold\">"
+                              "size=\"80000\" weight=\"ultrabold\">"
                               "00:00.0</span>" );
     else
         gtk_label_set_markup( GTK_LABEL( timerdata.label ),
                               "<span font_family=\"monospace\" "
-                              "size=\"70000\" weight=\"ultrabold\">"
+                              "size=\"80000\" weight=\"ultrabold\">"
                               "00:00:00.0</span>" );
     gtk_misc_set_alignment( GTK_MISC( timerdata.label ), 0.5f, 0.5f );
     gtk_container_add( GTK_CONTAINER( timerdata.vBox ), timerdata.label );
@@ -184,7 +191,7 @@ void stopish_stopwatch_label_timer_portrait( void )
         gtk_misc_set_alignment( GTK_MISC( timerdata.labelHour ), 0.0f, 0.5f );
         gtk_label_set_markup( GTK_LABEL( timerdata.labelHour ),
                               "<span font_family=\"monospace\" "
-                              "size=\"80000\" weight=\"ultrabold\">"
+                              "size=\"90000\" weight=\"ultrabold\">"
                               "00</span>" );
         gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelHour );
         gtk_container_add( GTK_CONTAINER( vBox ), hBox );
@@ -200,7 +207,7 @@ void stopish_stopwatch_label_timer_portrait( void )
     gtk_misc_set_alignment( GTK_MISC( timerdata.labelMinute ), 0.0f, 0.5f );
     gtk_label_set_markup( GTK_LABEL( timerdata.labelMinute ),
                           "<span font_family=\"monospace\" "
-                          "size=\"80000\" weight=\"ultrabold\">"
+                          "size=\"90000\" weight=\"ultrabold\">"
                           "00</span>" );
     gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelMinute );
     gtk_container_add( GTK_CONTAINER( vBox ), hBox );
@@ -215,7 +222,7 @@ void stopish_stopwatch_label_timer_portrait( void )
     gtk_misc_set_alignment( GTK_MISC( timerdata.labelSecond ), 0.0f, 0.5f );
     gtk_label_set_markup( GTK_LABEL( timerdata.labelSecond ),
                           "<span font_family=\"monospace\" "
-                          "size=\"80000\" weight=\"ultrabold\">"
+                          "size=\"90000\" weight=\"ultrabold\">"
                           "00.0</span>" );
     gtk_container_add( GTK_CONTAINER( hBox ), timerdata.labelSecond );
     gtk_container_add( GTK_CONTAINER( vBox ), hBox );
@@ -226,7 +233,6 @@ void stopish_stopwatch_label_timer_portrait( void )
 }
 
 
-
 //
 // Timer callback
 //
@@ -239,7 +245,7 @@ static gint timeout_cb( gpointer data )
     tempString = stopish_get_time_string(  );
     if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE ) {
         sprintf( formatBuffer, "<span font_family=\"monospace\" "
-                               "size=\"70000\" weight=\"ultrabold\">"
+                               "size=\"80000\" weight=\"ultrabold\">"
                                "%s</span>", tempString );
         gtk_label_set_markup( GTK_LABEL( timerdata.label ), formatBuffer );
     }
@@ -247,7 +253,7 @@ static gint timeout_cb( gpointer data )
         if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_HOUR ) {
             sprintf( tempBuffer, "%.2s", tempString );
             sprintf( formatBuffer, "<span font_family=\"monospace\" "
-                                   "size=\"80000\" weight=\"ultrabold\">"
+                                   "size=\"90000\" weight=\"ultrabold\">"
                                    "%s</span>", tempBuffer );
             gtk_label_set_markup( GTK_LABEL( timerdata.labelHour ),
                                   formatBuffer );
@@ -257,7 +263,7 @@ static gint timeout_cb( gpointer data )
         else
             sprintf( tempBuffer, "%.2s", tempString );
         sprintf( formatBuffer, "<span font_family=\"monospace\" "
-                               "size=\"80000\" weight=\"ultrabold\">"
+                               "size=\"90000\" weight=\"ultrabold\">"
                                "%s</span>", tempBuffer );
         gtk_label_set_markup( GTK_LABEL( timerdata.labelMinute ),
                               formatBuffer );
@@ -266,7 +272,7 @@ static gint timeout_cb( gpointer data )
         else
             sprintf( tempBuffer, "%.4s", tempString + 3 );
         sprintf( formatBuffer, "<span font_family=\"monospace\" "
-                               "size=\"80000\" weight=\"ultrabold\">"
+                               "size=\"90000\" weight=\"ultrabold\">"
                                "%s</span>", tempBuffer );
         gtk_label_set_markup( GTK_LABEL( timerdata.labelSecond ),
                               formatBuffer );
@@ -299,6 +305,7 @@ static void start_cb( GtkButton* button, gpointer data )
         stopish_set_mode( STOPISH_MODE_RESUME );
         g_source_remove( timerHandle );
         stopish_timer_save(  );
+        timerHandle = -1;
     }
 
     // allow user to reset timer
@@ -318,43 +325,38 @@ static void reset_cb( GtkButton* button, gpointer data )
     // set label text and remove timer handle
     gtk_button_set_label( GTK_BUTTON( data ), "Start" );
     stopish_set_mode( STOPISH_MODE_START );
-    if ( stopish_timer_get_precision(  ) == TIMER_PRECISION_MINUTE )
-        gtk_label_set_markup( GTK_LABEL( timerdata.label ),
-                              "<span font_family=\"monospace\" "
-                              "size=\"70000\" weight=\"ultrabold\">"
-                              "00:00.0</span>" );
+    if ( stopish_get_orientation(  ) == STOPISH_LANDSCAPE )
+        stopish_stopwatch_label_timer_landscape(  );
     else
-        gtk_label_set_markup( GTK_LABEL( timerdata.label ),
-                              "<span font_family=\"monospace\" "
-                              "size=\"70000\" weight=\"ultrabold\">"
-                              "00:00:00.0</span>" );
+        stopish_stopwatch_label_timer_portrait(  );
     g_source_remove( timerHandle );
+    timerHandle = -1;
 
     // add current time to history
     historyList = g_slist_prepend( historyList,
                                    ( gpointer ) stopish_get_time_string(  ) );
     sprintf( formatString, "<span size=\"large\">%s</span>",
              ( char * ) historyList->data );
-    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel1 ),
+    gtk_label_set_markup( GTK_LABEL( timerHistoryLabel[0] ),
                           formatString );
     tempList = historyList;
     tempList = g_slist_next( tempList );
     if ( tempList ) {
-        gtk_label_set_text( GTK_LABEL( timerHistoryLabel2 ),
+        gtk_label_set_text( GTK_LABEL( timerHistoryLabel[1] ),
                             ( char * ) tempList->data );
     }
     tempList = g_slist_next( tempList );
     if ( tempList ) {
         sprintf( formatString, "<span size=\"small\">%s</span>",
                  ( char * ) tempList->data );
-        gtk_label_set_markup( GTK_LABEL( timerHistoryLabel3 ),
+        gtk_label_set_markup( GTK_LABEL( timerHistoryLabel[2] ),
                               formatString );
     }
     tempList = g_slist_next( tempList );
     if ( tempList ) {
         sprintf( formatString, "<span size=\"x-small\">%s</span>",
                  ( char * ) tempList->data );
-        gtk_label_set_markup( GTK_LABEL( timerHistoryLabel4 ),
+        gtk_label_set_markup( GTK_LABEL( timerHistoryLabel[3] ),
                               formatString );
     }
 
index b8923ab..af7a7da 100644 (file)
@@ -35,6 +35,7 @@
 typedef struct _AppData AppData;
 struct _AppData {
     GtkWindow *main_window;
+    GtkWindow *countdown_window;
     osso_context_t *osso_context;
     DBusConnection *system_bus;
 };
@@ -43,17 +44,15 @@ struct _AppData {
 static AppData appdata;
 static int stopishMode = STOPISH_MODE_START;
 static int stopishOrientation = STOPISH_LANDSCAPE;
+static int stopishType = STOPISH_TYPE_STOPWATCH;
 
 
 //Prototypes
 gint dbus_callback( const gchar *interface, const gchar *method,
                        GArray *arguments, gpointer data, osso_rpc_t *retval );
 static void main_menu( GtkWindow *window );
+static void change_type_cb( GtkButton* button, gpointer data );
 static void close_cb( GtkButton* button, gpointer data );
-static gboolean focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
-                             gpointer data );
-static gboolean focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
-                              gpointer data );
 static void accelerometer_enable( void );
 static void accelerometer_disable( void );
 static DBusHandlerResult mce_filter_func( DBusConnection * connection,
@@ -84,9 +83,9 @@ int main( int argc, char *argv[] )
     g_signal_connect( G_OBJECT( appdata.main_window ), "destroy",
                       G_CALLBACK( close_cb ), appdata.main_window );
     g_signal_connect( G_OBJECT( appdata.main_window ), "focus-in-event",
-                      G_CALLBACK( focus_in_cb ), NULL );
+                      G_CALLBACK( stopish_focus_in_cb ), NULL );
     g_signal_connect( G_OBJECT( appdata.main_window ), "focus-out-event",
-                      G_CALLBACK( focus_out_cb ), NULL );
+                      G_CALLBACK( stopish_focus_out_cb ), NULL );
 
     // setup main menu
     main_menu( appdata.main_window );
@@ -131,6 +130,36 @@ gint dbus_callback( const gchar *interface, const gchar *method,
 }
 
 
+void stopish_about_cb( GtkButton* button, gpointer data )
+{
+    GdkPixbuf *logo;
+    GError *error;
+    GtkWidget *dialog;
+    char *authors[2];
+
+    authors[0] = strdup( "Michael Cronenworth" );
+    authors[1] = NULL;
+
+    dialog = gtk_about_dialog_new(  );
+
+    gtk_about_dialog_set_program_name( GTK_ABOUT_DIALOG( dialog ),
+                                       "Stopish" );
+    gtk_about_dialog_set_version( GTK_ABOUT_DIALOG( dialog ),
+                                  STOPISH_VERSION_STR );
+    gtk_about_dialog_set_authors( GTK_ABOUT_DIALOG( dialog ),
+                                  ( const char ** ) authors );
+    logo = gdk_pixbuf_new_from_file( "/usr/share/icons/hicolor/40x40/hildon/stopish.png",
+                                     &error );
+    gtk_about_dialog_set_logo( GTK_ABOUT_DIALOG( dialog ),
+                               logo );
+
+    gtk_dialog_run( GTK_DIALOG( dialog ) );
+
+    gtk_widget_destroy( dialog );
+    free( authors[0] );
+}
+
+
 int stopish_get_mode( void )
 {
     return stopishMode;
@@ -143,17 +172,60 @@ void stopish_set_mode( int newMode )
 }
 
 
+int stopish_get_type( void )
+{
+    return stopishType;
+}
+
+
+void stopish_set_type( int newType )
+{
+    stopishType = newType;
+}
+
+
 int stopish_get_orientation( void )
 {
     return stopishOrientation;
 }
 
 
+gboolean stopish_focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
+                              gpointer data )
+{
+    // enable accelerometer hardware for portrait mode support
+    accelerometer_enable(  );
+
+    return FALSE;
+}
+
+
+gboolean stopish_focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
+                               gpointer data )
+{
+    // disable accelerometer for battery savings
+    accelerometer_disable(  );
+
+    return FALSE;
+}
+
+
 static void main_menu( GtkWindow *window )
 {
-    GtkWidget *menu, *radio;
+    HildonAppMenu *menu;
+    GtkWidget *button, *radio;
+
+    menu = ( HildonAppMenu * ) hildon_app_menu_new(  );
 
-    menu = hildon_app_menu_new(  );
+    button = gtk_button_new_with_label( "Countdown" );
+    g_signal_connect_after( G_OBJECT( button ), "clicked",
+                            G_CALLBACK( change_type_cb ), NULL );
+    hildon_app_menu_append( menu, GTK_BUTTON( button ) );
+
+    button = gtk_button_new_with_label( "About" );
+    g_signal_connect_after( G_OBJECT( button ), "clicked",
+                            G_CALLBACK( stopish_about_cb ), NULL );
+    hildon_app_menu_append( menu, GTK_BUTTON( button ) );
 
     // Hour preference
     radio = gtk_radio_button_new_with_label( NULL, "Hour" );
@@ -170,42 +242,30 @@ static void main_menu( GtkWindow *window )
     hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
 
     // default to minute
-    gtk_toggle_button_set_active( radio, TRUE );
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radio ), TRUE );
 
-    gtk_widget_show_all( menu );
+    gtk_widget_show_all( GTK_WIDGET( menu ) );
 
     hildon_window_set_app_menu( HILDON_WINDOW( window ), menu );
 }
 
 
-static void close_cb( GtkButton* button, gpointer data )
-{
-    // disable accelerometer for battery savings
-    accelerometer_disable(  );
-
-    // destroy main window and exit gtk main loop
-    gtk_widget_destroy( GTK_WIDGET( data ) );
-    gtk_main_quit(  );
-}
-
-
-static gboolean focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
-                             gpointer data )
+static void change_type_cb( GtkButton* button, gpointer data )
 {
-    // enable accelerometer hardware for portrait mode support
-    accelerometer_enable(  );
-
-    return FALSE;
+    stopish_stopwatch_reset(  );
+    stopishType = STOPISH_TYPE_COUNTDOWN;
+    stopish_countdown_new(  );
 }
 
 
-static gboolean focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
-                              gpointer data )
+static void close_cb( GtkButton* button, gpointer data )
 {
     // disable accelerometer for battery savings
     accelerometer_disable(  );
 
-    return FALSE;
+    // destroy main window and exit gtk main loop
+    gtk_widget_destroy( GTK_WIDGET( data ) );
+    gtk_main_quit(  );
 }
 
 
@@ -248,13 +308,19 @@ static DBusHandlerResult mce_filter_func( DBusConnection * connection,
             if ( !strcmp( rotation, MCE_ORIENTATION_PORTRAIT ) ) {
                 hildon_gtk_window_set_portrait_flags( GTK_WINDOW( appdata.main_window ),
                                                       HILDON_PORTRAIT_MODE_REQUEST );
-                stopish_stopwatch_label_timer_portrait(  );
+                if ( stopishType == STOPISH_TYPE_STOPWATCH )
+                    stopish_stopwatch_label_timer_portrait(  );
+                else
+                    stopish_countdown_label_timer_portrait(  );
                 stopishOrientation = STOPISH_PORTRAIT;
             }
             else {
                 hildon_gtk_window_set_portrait_flags( GTK_WINDOW( appdata.main_window ),
                                                       ~HILDON_PORTRAIT_MODE_REQUEST );
-                stopish_stopwatch_label_timer_landscape(  );
+                if ( stopishType == STOPISH_TYPE_STOPWATCH )
+                    stopish_stopwatch_label_timer_landscape(  );
+                else
+                    stopish_countdown_label_timer_landscape(  );
                 stopishOrientation = STOPISH_LANDSCAPE;
             }
         }
index 1b87d87..d5d378c 100644 (file)
 
 #include <libosso.h>
 
+#define STOPISH_VERSION_NUM 0.9.3
+#define STOPISH_VERSION_STR "0.9.3"
+
 #define STOPISH_MODE_START  0
 #define STOPISH_MODE_PAUSE  1
 #define STOPISH_MODE_RESUME 2
 
+#define STOPISH_TYPE_STOPWATCH 0
+#define STOPISH_TYPE_COUNTDOWN 1
+
 #define STOPISH_PORTRAIT  0
 #define STOPISH_LANDSCAPE 1
 
 // stopish.c
 gint dbus_callback( const gchar *interface, const gchar *method,
                        GArray *arguments, gpointer data, osso_rpc_t *retval );
+void stopish_about_cb( GtkButton* button, gpointer data );
 int stopish_get_mode( void );
+int stopish_get_type( void );
 int stopish_get_orientation( void );
 void stopish_set_mode( int newMode );
+void stopish_set_type( int newType );
+gboolean stopish_focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
+                               gpointer data );
+gboolean stopish_focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
+                               gpointer data );
+
+// stopish-countdown.c
+void stopish_countdown_new( void );
+void stopish_countdown_label_timer_landscape( void );
+void stopish_countdown_label_timer_portrait( void );
 
 // stopish-stopwatch.c
 GtkWindow *stopish_stopwatch_new( void );
+void stopish_stopwatch_reset( void );
 void stopish_stopwatch_perf_timer_hour( GtkRadioButton* radio, GtkLabel *label );
 void stopish_stopwatch_perf_timer_minute( GtkRadioButton* radio, GtkLabel *label );
 void stopish_stopwatch_label_timer_landscape( void );
index a17e21f..fe42c75 100644 (file)
@@ -60,13 +60,26 @@ char *stopish_get_time_string( void )
         h = m = s = ss = 0;
     }
 
+    if ( stopish_get_type(  ) == STOPISH_TYPE_COUNTDOWN ) {
+        h = -h;
+        m = -m;
+        s = -s;
+        ss = -ss;
+    }
+    // countdown check
+    if ( stopish_get_type(  ) == STOPISH_TYPE_COUNTDOWN &&
+         ( h == 0 && m == 0 && s == 0 && ss == 0 ) )
+        return NULL;
+
     timeBuffer = malloc( 64 );
     if ( timerPrecision == TIMER_PRECISION_MINUTE )
         sprintf( timeBuffer, "%.02d:%.02d.%.1d",
-                 m, s, ss );
+                 ( unsigned int ) m, ( unsigned int ) s,
+                 ( unsigned int ) ss );
     else
         sprintf( timeBuffer, "%.02d:%.02d:%.02d.%.1d",
-                 h, m, s, ss );
+                 ( unsigned int ) h, ( unsigned int ) m,
+                 ( unsigned int ) s, ( unsigned int ) ss );
 
     return timeBuffer;
 }