Implemented typing in grid, including typing modes
authorHarishankar <v.harishankar@gmail.com>
Tue, 7 Dec 2010 11:11:56 +0000 (16:41 +0530)
committerHarishankar <v.harishankar@gmail.com>
Tue, 7 Dec 2010 11:11:56 +0000 (16:41 +0530)
Implemented typing in the grid with both across and down modes

player_mainwindow.py

index 3ea5420..366cbfa 100644 (file)
@@ -8,96 +8,176 @@ import cPickle
 import pygtk
 pygtk.require20 ()
 import gtk
-import pango
+import cairo
+
 import crosswordpuzzle
 
 class MainWindow:
+       # typing mode constants
+       ACROSS = 1
+       DOWN = 2
+
        def gtk_main_quit (self, *args):
+               gtk.main_quit ()
+
+       # callback for menu item quit activated event
+       def on_quit_activate (self, menuitem):
                if self.puzzle:
                        dlg = gtk.MessageDialog (self.window, gtk.DIALOG_MODAL,
                                        gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
                                        "Puzzle is open. Are you sure you wish to quit?")
-                       if dlg.run () == gtk.RESPONSE_NO:
+                       if dlg.run () <> gtk.RESPONSE_YES:
                                dlg.destroy ()
-                               return
+                               return False
                        dlg.destroy ()
 
-               gtk.main_quit ()
-
-       # callback for menu item quit activated event
-       def on_quit_activate (self, menuitem):
                self.gtk_main_quit ()
 
        # callback for puzzle grid mouse button release event
        def on_puzzlegrid_button_press_event (self, drawarea, event):
-               self.window.set_focus (drawarea)
-               return True
+               # set the focus on the puzzle grid
+               if self.puzzle:
+                       self.window.set_focus (drawarea)
+
+                       col = int (event.x / 30)
+                       row = int (event.y / 30)
+
+                       if col < self.puzzle.cols and row < self.puzzle.rows:
+                               if (self.puzzle.data[row][col].occupied_across is True or
+                               self.puzzle.data[row][col].occupied_down is True):
+                                       self.selected_col = col
+                                       self.selected_row = row
+                                       drawarea.queue_draw ()
+
+               return False
 
        # moving the current selection in grid by one up or down
        def move_selection_updown (self, step):
                # increase or reduce the row by step until an occupied grid is found
                # black block
-               last_occupied_row = self.selected_row
-               while True:
-                       self.selected_row += step
-                       if self.selected_row < 0 or self.selected_row >= self.puzzle.rows:
-                               self.selected_row = last_occupied_row
-                               break
-                       if (self.puzzle.data[self.selected_row][self.selected_col].occupied_across is True
-                               or self.puzzle.data[self.selected_row][self.selected_col].occupied_down is True):
-                               break
+               if self.puzzle:
+                       last_occupied_row = self.selected_row
+                       while True:
+                               self.selected_row += step
+                               if self.selected_row < 0 or self.selected_row >= self.puzzle.rows:
+                                       self.selected_row = last_occupied_row
+                                       break
+                               if (self.puzzle.data[self.selected_row][self.selected_col].occupied_across is True
+                                       or self.puzzle.data[self.selected_row][self.selected_col].occupied_down is True):
+                                       break
 
        # moving the current selection in grid by one across either way
        def move_selection_across (self, step):
                # increase or reduce the row by step until an occupied grid is found
                # black block
-               last_occupied_col = self.selected_col
-               while True:
-                       self.selected_col += step
-                       if self.selected_col < 0 or self.selected_col >= self.puzzle.cols:
-                               self.selected_col = last_occupied_col
-                               break
-                       if (self.puzzle.data[self.selected_row][self.selected_col].occupied_across is True
-                               or self.puzzle.data[self.selected_row][self.selected_col].occupied_down is True):
-                               break
+               if self.puzzle:
+                       last_occupied_col = self.selected_col
+                       while True:
+                               self.selected_col += step
+                               if self.selected_col < 0 or self.selected_col >= self.puzzle.cols:
+                                       self.selected_col = last_occupied_col
+                                       break
+                               if (self.puzzle.data[self.selected_row][self.selected_col].occupied_across is True
+                                       or self.puzzle.data[self.selected_row][self.selected_col].occupied_down is True):
+                                       break
+
+       # set the guessed character in the grid at selected location and move the
+       # selection across or down as the case may be
+       def set_guess (self, guess_char):
+               if self.puzzle:
+                       self.puzzle.data[self.selected_row][self.selected_col].guess = guess_char.upper ()
+                       # across mode typing
+                       if self.typing_mode == self.ACROSS:
+                               # move by one character across but only if there is no block
+                               # in between
+                               old_col = self.selected_col
+                               self.move_selection_across (1)
+                               if abs (self.selected_col - old_col) > 1:
+                                       self.selected_col = old_col
+                       # down mode typing
+                       else:
+                               # move by one character down but only if there is no block
+                               # in between
+                               old_row = self.selected_row
+                               self.move_selection_updown (1)
+                               if abs (self.selected_row - old_row) > 1:
+                                       self.selected_row = old_row
+
+       # delete the guessed char in the previous row/col depending on the input mode
+       # If input mode is ACROSS then delete guessed char at previous column else
+       # at previous row
+       def delete_prev_guess (self):
+               if self.puzzle:
+                       if self.typing_mode == self.ACROSS:
+                               # prevent deleting characters when there is a gap
+                               old_sel_col = self.selected_col
+                               self.move_selection_across (-1)
+                               # only if there is no block inbetween delete
+                               if abs (self.selected_col - old_sel_col) <= 1:
+                                       self.puzzle.data[self.selected_row][self.selected_col].guess = None
+                               # reset selection
+                               else:
+                                       self.selected_col = old_sel_col
 
        # callback for puzzle grid key release event
        def on_puzzlegrid_key_press_event (self, drawarea, event):
-               key = gtk.gdk.keyval_name (event.keyval)
-
-               if event.state == gtk.gdk.SHIFT_MASK and key == "Up":
-                       # reduce the row by 1 until you find an occupied grid and not a
-                       # black block
-                       self.move_selection_updown (-1)
-                       drawarea.queue_draw ()
-               elif event.state == gtk.gdk.SHIFT_MASK and key == "Down":
-                       # increase the row by 1 until you find an occupied grid and not a
-                       # black block
-                       self.move_selection_updown (1)
-                       drawarea.queue_draw ()
-               elif event.state == gtk.gdk.SHIFT_MASK and key == "Right":
-                       # increase the column by 1 until you find an occupied grid and not
-                       # a black block
-                       self.move_selection_across (1)
-                       drawarea.queue_draw ()
-               elif event.state == gtk.gdk.SHIFT_MASK and key == "Left":
-                       # decrease the column by 1 until you find an occupied grid and not
-                       # a black block
-                       self.move_selection_across (-1)
-                       drawarea.queue_draw ()
+               if self.puzzle:
+                       key = gtk.gdk.keyval_name (event.keyval)
+
+                       if event.state == gtk.gdk.SHIFT_MASK and key == "Up":
+                               # reduce the row by 1 until you find an occupied grid and not a
+                               # black block
+                               self.move_selection_updown (-1)
+                               self.typing_mode = self.DOWN
+                               drawarea.queue_draw ()
+                       elif event.state == gtk.gdk.SHIFT_MASK and key == "Down":
+                               # increase the row by 1 until you find an occupied grid and not a
+                               # black block
+                               self.move_selection_updown (1)
+                               self.typing_mode = self.DOWN
+                               drawarea.queue_draw ()
+                       elif event.state == gtk.gdk.SHIFT_MASK and key == "Right":
+                               # increase the column by 1 until you find an occupied grid and not
+                               # a black block
+                               self.move_selection_across (1)
+                               self.typing_mode = self.ACROSS
+                               drawarea.queue_draw ()
+                       elif event.state == gtk.gdk.SHIFT_MASK and key == "Left":
+                               # decrease the column by 1 until you find an occupied grid and not
+                               # a black block
+                               self.move_selection_across (-1)
+                               self.typing_mode = self.ACROSS
+                               drawarea.queue_draw ()
+                       # if it is A-Z or a-z then
+                       elif len (key) == 1 and key.isalpha ():
+                               self.set_guess (key)
+                               drawarea.queue_draw ()
+                       # if it is the delete key then delete character at selected row/col
+                       elif key == "Delete":
+                               self.puzzle.data[self.selected_row][self.selected_col].guess = None
+                               drawarea.queue_draw ()
+                       # if it is backspace key then delete character at previous row/col
+                       # depending on the input mode. If across editing mode, then delete
+                       # at previous column else at previous row
+                       elif key == "BackSpace":
+                               self.delete_prev_guess ()
+                               drawarea.queue_draw ()
+
                return False
 
        # puzzle grid focus in event
        def on_puzzlegrid_focus_out_event (self, drawarea, event):
-               col = drawarea.window.get_colormap ().alloc_color (gtk.gdk.Color ("gray"))
-               drawarea.window.set_background (col)
+               if self.puzzle:
+                       col = drawarea.window.get_colormap ().alloc_color (gtk.gdk.Color ("gray"))
+                       drawarea.window.set_background (col)
 
                return False
 
        # puzzle grid focus out event
        def on_puzzlegrid_focus_in_event (self, drawarea, event):
-               col = drawarea.window.get_colormap ().alloc_color (gtk.gdk.Color ("white"))
-               drawarea.window.set_background (col)
+               if self.puzzle:
+                       col = drawarea.window.get_colormap ().alloc_color (gtk.gdk.Color ("white"))
+                       drawarea.window.set_background (col)
                return False
 
        # callback for drawing the puzzle grid
@@ -125,7 +205,7 @@ class MainWindow:
                                        else:
                                                # if selected row/column
                                                if row == self.selected_row and col == self.selected_col:
-                                                       ctx.set_source_rgb (1, 1, 0.6)
+                                                       ctx.set_source_rgb (1, 1, 0)
                                                        ctx.rectangle (col*30,row*30, 30, 30)
                                                        ctx.fill ()
                                                else:
@@ -139,12 +219,27 @@ class MainWindow:
                                                # if numbered
                                                if self.puzzle.data[row][col].numbered <> 0:
                                                        ctx.set_source_rgb (0, 0, 0)
-                                                       ctx.select_font_face ("Sans 7")
+                                                       ctx.select_font_face ("Serif")
+                                                       ctx.set_font_size (10)
                                                        ctx.move_to (col*30+2, row*30+10)
                                                        ctx.show_text (str(self.puzzle.data[row][col].numbered))
 
+                                               # if there is a guessed character at the location
+                                               # and it is not revealed as a solution
+                                               if (self.puzzle.data[row][col].guess and
+                                                       self.puzzle.data[row][col].revealed is False and
+                                                       (self.puzzle.data[row][col].occupied_across is True
+                                                       or self.puzzle.data[row][col].occupied_down is True)):
+                                                       ctx.set_source_rgb (0, 0, 0)
+                                                       ctx.select_font_face ("Serif", cairo.FONT_SLANT_NORMAL,
+                                                                       cairo.FONT_WEIGHT_BOLD)
+                                                       ctx.set_font_size (16)
+                                                       ctx.move_to (col*30+10, row*30+20)
+                                                       ctx.show_text (self.puzzle.data[row][col].guess)
+
                        return False
 
+       # load clues to the list
        def load_clues (self):
                # get the clues list store objects
                across = self.ui.get_object ("clues_across")
@@ -176,6 +271,9 @@ class MainWindow:
                        # set selected initial row and column to 0
                        self.selected_row = 0
                        self.selected_col = 0
+                       # set the typing mode to default - across
+                       self.typing_mode = self.ACROSS
+
                        self.window.set_title ("GetAClue player - " + file)
                        # load the clues
                        self.load_clues ()
@@ -212,7 +310,7 @@ class MainWindow:
                self.window = self.ui.get_object ("mainwindow")
                self.window.show ()
 
-               # set the cell renderer
+               # set the cell renderer for tree views
                cell = gtk.CellRendererText ()
                tree_acol1 = self.ui.get_object ("tree_clues_across").get_column (0)
                tree_acol2 = self.ui.get_object ("tree_clues_across").get_column (1)