Functionality for keyboard and mouse in puzzle area
[wordblah.git] / wordblox_player.c
index 2904929..46a41fd 100644 (file)
 #include "wordblox.h"
 
 GtkWidget *window; 
+GtkListStore *across_store;
+GtkListStore *down_store;
 
-struct MainAppData {
-       Puzzle puzzle;
-       char filename[65535];
-       bool is_loaded;
-} app_data;
+MainPlayerData app_data;
+
+/* update the clue items store */
+void update_clue_items ()
+{
+       gtk_list_store_clear (across_store);
+       gtk_list_store_clear (down_store);
+       
+       /* if the puzzle is loaded */
+       if (app_data.is_loaded == true)
+       {
+               /* iterate through the puzzle grid and gte the clues */
+               for (int i = 0; i < app_data.puzzle.grid_size; i ++)
+               {
+                       for (int j = 0; j < app_data.puzzle.grid_size; j ++)
+                       {
+                               /* if it is the start of an across word */
+                               if (app_data.puzzle.start_across_word[i][j] != -1)
+                               {
+                                       GtkTreeIter iter;
+                                                                                       
+                                       gtk_list_store_append (across_store, &iter);
+                                       gtk_list_store_set (across_store, &iter, 0,
+                                                                               app_data.puzzle.start_across_word[i][j],
+                                                                               1, app_data.puzzle.clue_across[i][j],
+                                                                               -1);
+                               }
+                               /* if it is the start of a down word */
+                               if (app_data.puzzle.start_down_word[i][j] != -1)
+                               {
+                                       GtkTreeIter iter;
+                                       gtk_list_store_append (down_store, &iter);
+                                       gtk_list_store_set (down_store, &iter, 0,
+                                                                               app_data.puzzle.start_down_word[i][j],
+                                                                               1, app_data.puzzle.clue_down[i][j],
+                                                                               -1);
+                               }
+                       }
+               }
+       } 
+}
+
+/* slot for handling mouse button event for puzzle drawing area */
+gboolean on_puzzle_area_button_press_event (GtkWidget *widget, 
+                                                                       GdkEventButton *event, gpointer data)
+{
+       if (event->type == GDK_BUTTON_PRESS && event->button == 1)
+       {
+               int col = (event->x - 5) / GRID_PIXELS;
+               int row = (event->y - 5) / GRID_PIXELS;
+       
+               if (app_data.puzzle.chars[row][col] != '#')
+               {
+                       if (row < app_data.puzzle.grid_size && 
+                               col < app_data.puzzle.grid_size)
+                       {
+                               app_data.cur_row = row;
+                               app_data.cur_col = col;
+                       }
+               }
+       }
+       
+       gtk_widget_queue_draw_area (widget, 0, 0,  
+               app_data.puzzle.grid_size*GRID_PIXELS+10, 
+               app_data.puzzle.grid_size*GRID_PIXELS+10);
+       
+
+               
+       return FALSE;   
+}
+
+/* slot for handling key press event for puzzle drawing area */
+gboolean on_puzzle_area_key_press_event (GtkWidget *widget, 
+                                                                       GdkEventKey *event, gpointer data)
+{
+       /* respond to key events only if the puzzle is loaded */
+       if (app_data.is_loaded == true)
+       {
+               switch (event->keyval)
+               {
+                       case GDK_KEY_Down : move_current_row (&app_data, DIR_FORWARD);
+                                                               break;
+                       case GDK_KEY_Up   : move_current_row (&app_data, DIR_BACK);
+                                                               break;
+                       case GDK_KEY_Right: move_current_col (&app_data, DIR_FORWARD);
+                                                               break;
+                       case GDK_KEY_Left : move_current_col (&app_data, DIR_BACK);
+                                                               break;
+                       case GDK_KEY_Delete:
+                       case GDK_KEY_space: 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = ' ';
+                                                               break;                  
+                       case GDK_KEY_a    :
+                       case GDK_KEY_A    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'A';
+                                                               break;
+                       case GDK_KEY_b    :
+                       case GDK_KEY_B    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'B';
+                                                               break;
+                       case GDK_KEY_c    :
+                       case GDK_KEY_C    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'C';
+                                                               break;
+                       case GDK_KEY_d    :
+                       case GDK_KEY_D    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'D';
+                                                               break;
+                       case GDK_KEY_e    :
+                       case GDK_KEY_E    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'E';
+                                                               break;
+                       case GDK_KEY_f    :
+                       case GDK_KEY_F    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'F';            
+                                                               break;
+                       case GDK_KEY_g    :
+                       case GDK_KEY_G    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'G';
+                                                               break;
+                       case GDK_KEY_h    :
+                       case GDK_KEY_H    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'H';
+                                                               break;
+                       case GDK_KEY_i    :
+                       case GDK_KEY_I    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'I';
+                                                               break;
+                       case GDK_KEY_j    :
+                       case GDK_KEY_J    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'J';
+                                                               break;
+                       case GDK_KEY_k    :
+                       case GDK_KEY_K    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'K';
+                                                               break;
+                       case GDK_KEY_l    :
+                       case GDK_KEY_L    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'L';
+                                                               break;
+                       case GDK_KEY_m    :
+                       case GDK_KEY_M    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'M';
+                                                               break;
+                       case GDK_KEY_n    :
+                       case GDK_KEY_N    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'N';
+                                                               break;
+                       case GDK_KEY_o    :
+                       case GDK_KEY_O    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'O';
+                                                               break;
+                       case GDK_KEY_p    :
+                       case GDK_KEY_P    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'P';
+                                                               break;
+                       case GDK_KEY_q    :
+                       case GDK_KEY_Q    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'Q';
+                                                               break;
+                       case GDK_KEY_r    :
+                       case GDK_KEY_R    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'R';
+                                                               break;
+                       case GDK_KEY_s    :
+                       case GDK_KEY_S    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'S';
+                                                               break;
+                       case GDK_KEY_t    :
+                       case GDK_KEY_T    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'T';
+                                                               break;
+                       case GDK_KEY_u    :
+                       case GDK_KEY_U    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'U';
+                                                               break;
+                       case GDK_KEY_v    :
+                       case GDK_KEY_V    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'V';
+                                                               break;
+                       case GDK_KEY_w    :
+                       case GDK_KEY_W    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'W';
+                                                               break;
+                       case GDK_KEY_x    :
+                       case GDK_KEY_X    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'X';
+                                                               break;
+                       case GDK_KEY_y    :
+                       case GDK_KEY_Y    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'Y';
+                                                               break;
+                       case GDK_KEY_z    :
+                       case GDK_KEY_Z    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'Z';
+                                                               break;
+                       default                   : return FALSE;
+                                                                               
+               }
+       }
+       
+       gtk_widget_queue_draw_area (widget, 0, 0,  
+               app_data.puzzle.grid_size*GRID_PIXELS+10, 
+               app_data.puzzle.grid_size*GRID_PIXELS+10);      
+       
+       return FALSE;
+}
 
 /* slot for drawing the puzzle */
 gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
@@ -18,22 +222,43 @@ gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
        /* if a puzzle is loaded */
        if (app_data.is_loaded == true)
        {
-               GdkRGBA colorfore, colorback;
+               GdkRGBA colorfore, colorback, colorblue, colorbacksel;
                gdk_rgba_parse (&colorfore, "#000000"); 
                gdk_rgba_parse (&colorback, "#ffffff");
+               gdk_rgba_parse (&colorblue, "#0000dd");
+               gdk_rgba_parse (&colorbacksel, "#ffffaa");
                cairo_set_line_width (cr, 3);
                
                /* set the size of the drawing area */
-               gtk_widget_set_size_request (widget, app_data.puzzle.grid_size*30+5, 
-                                                                                       app_data.puzzle.grid_size*30+5);
+               gtk_widget_set_size_request (widget, 
+                                                               app_data.puzzle.grid_size*GRID_PIXELS+10, 
+                                                               app_data.puzzle.grid_size*GRID_PIXELS+10);
                                                                
                /* Draw the grid */                     
                for (int i = 0; i < app_data.puzzle.grid_size; i ++)
                {
                        for (int j = 0; j < app_data.puzzle.grid_size; j ++)
                        {
-                               cairo_rectangle (cr, j*30+5, i*30+5, 30, 30);
+                               /* if it is the current selection or if -1 is the current 
+                               selection then let the current selection be the first word */
+                               if (app_data.cur_col == -1 && app_data.cur_row == -1)
+                               {
+                                       if (app_data.puzzle.start_across_word[i][j] == 1)
+                                       {
+                                               app_data.cur_row = i;
+                                               app_data.cur_col = j;
+                                       }
+                                       else if (app_data.puzzle.start_down_word[i][j] == 1)
+                                       {
+                                               app_data.cur_row = i; 
+                                               app_data.cur_col = j;
+                                       }
+                               }
+                       
                                gdk_cairo_set_source_rgba (cr, &colorfore);
+                               cairo_rectangle (cr, j*GRID_PIXELS+5, i*GRID_PIXELS+5, 
+                                                                       GRID_PIXELS, GRID_PIXELS);
+
                                cairo_stroke (cr);
                                
                                /* if it is not a blank grid then set the background color
@@ -41,9 +266,49 @@ gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
                                if (app_data.puzzle.chars[i][j] != '#')
                                        gdk_cairo_set_source_rgba (cr, &colorback);
                                
-                               cairo_rectangle (cr, j*30+5, i*30+5, 30, 30);
-
+                               /* if it is a current selection then set the background 
+                               to yellow */
+                               if (app_data.cur_row == i && app_data.cur_col == j)
+                                       gdk_cairo_set_source_rgba (cr, &colorbacksel);
+                               
+                               cairo_rectangle (cr, j*GRID_PIXELS+5, i*GRID_PIXELS+5, 
+                                                                       GRID_PIXELS, GRID_PIXELS);
                                cairo_fill (cr);
+                               
+                               /* draw the word number if it is the start of a word */
+                               if (app_data.puzzle.start_across_word[i][j] != -1 || 
+                                       app_data.puzzle.start_down_word[i][j] != -1)
+                               {
+                                       int num;
+                                       if (app_data.puzzle.start_across_word[i][j] != -1)
+                                               num = app_data.puzzle.start_across_word[i][j];
+                                       else
+                                               num = app_data.puzzle.start_down_word[i][j];
+                               
+                                       gdk_cairo_set_source_rgba (cr, &colorblue);     
+                                       cairo_select_font_face (cr, "sans serif", 
+                                                                                       CAIRO_FONT_SLANT_NORMAL,
+                                                                                       CAIRO_FONT_WEIGHT_NORMAL);
+                                       cairo_set_font_size (cr, 11);
+                                       cairo_move_to (cr, j*GRID_PIXELS+7, i*GRID_PIXELS+15);
+                                       char cnum[3];
+                                       sprintf (cnum, "%d", num);
+                                       cairo_show_text (cr, (const char*)cnum);
+                               }
+                               
+                               /* draw the answer if it is there */
+                               gdk_cairo_set_source_rgba (cr, &colorfore);     
+                               cairo_select_font_face (cr, "sans serif", 
+                                                                               CAIRO_FONT_SLANT_NORMAL,
+                                                                               CAIRO_FONT_WEIGHT_BOLD);
+                               
+                               cairo_set_font_size (cr, 16);
+                               cairo_move_to (cr, j*GRID_PIXELS+GRID_PIXELS/2, 
+                                                               i*GRID_PIXELS+GRID_PIXELS-10);
+                               char ctxt[3];
+                               sprintf (ctxt, "%c", app_data.char_ans[i][j]);
+                               cairo_show_text (cr, (const char*) ctxt);
+
                        }
                }
        }
@@ -52,6 +317,18 @@ gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
 
 }
 
+/* slot for reveal solution menu */
+void on_menu_reveal_solution_activate (GtkMenuItem *item, gpointer *data)
+{
+       /* TODO */
+}
+
+/* slot for save grid state menu */
+void on_menu_save_grid_state_activate (GtkMenuItem *item, gpointer *data)
+{
+       /* TODO */
+}
+
 /* slot for exit menu */
 void on_menu_exit_activate (GtkMenuItem *item, gpointer data)
 {
@@ -75,11 +352,11 @@ void on_menu_open_activate (GtkMenuItem *item, GtkDrawingArea* area)
        {
                char *filename;
                filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
-               app_data.puzzle = load_puzzle (filename);
-               app_data.is_loaded = true;
-               strcpy (app_data.filename, filename);           
+               MainPlayerData temp;
+               reset_player_data (&temp, filename);
+
                /* if the grid is not frozen then the game cannot be played */
-               if (app_data.puzzle.grid_frozen == false)
+               if (temp.is_loaded == false)
                {
                        GtkWidget *errordlg ;
                        errordlg = gtk_message_dialog_new (GTK_WINDOW(window), 
@@ -89,11 +366,16 @@ void on_menu_open_activate (GtkMenuItem *item, GtkDrawingArea* area)
                                                                                                UNFROZEN_GRID_PLAYER);
                        gtk_dialog_run (GTK_DIALOG(errordlg));
                        gtk_widget_destroy (errordlg);
-                       app_data.is_loaded = false;
                }
-               
-               gtk_widget_queue_draw_area (GTK_WIDGET (area), 0, 0, 305, 305);
-               
+               else
+               {
+                       app_data = temp;
+                       gtk_widget_queue_draw_area (GTK_WIDGET (area), 0, 0, 
+                                                                               app_data.puzzle.grid_size*30+10, 
+                                                                               app_data.puzzle.grid_size*30+10);
+
+               }
+               update_clue_items ();           
                g_free (filename);
        }
        
@@ -140,9 +422,22 @@ int main (int argc, char *argv [])
        else 
        {
                window = GTK_WIDGET (gtk_builder_get_object (builder, "main_window") );
+               across_store = GTK_LIST_STORE (gtk_builder_get_object
+                                                                                       (builder, "store_across_clues"));
+               down_store = GTK_LIST_STORE (gtk_builder_get_object 
+                                                                                       (builder, "store_down_clues"));
+                                                                                       
                if (window != NULL)
                {
-                       gtk_window_set_default_icon (icon);             
+                       gtk_window_set_default_icon (icon);
+                       
+                       GtkWidget *draw_area = GTK_WIDGET (
+                                                       gtk_builder_get_object(builder, "puzzle_area"));
+                       
+                       /* make drawing area respond to mouse event */
+                       gtk_widget_set_events(draw_area,
+                                       gtk_widget_get_events(draw_area) 
+                                               | GDK_BUTTON_PRESS_MASK);
                
                        gtk_builder_connect_signals (builder, NULL);
                        g_object_unref (builder);