1 # Get A Clue (C) 2010 V. Harishankar
2 # Crossword puzzle maker program
3 # Licensed under the GNU GPL v3
5 # Main window class for GetAClue player
12 import crosswordpuzzle
15 def gtk_main_quit (self
, *args
):
17 dlg
= gtk
.MessageDialog (self
.window
, gtk
.DIALOG_MODAL
,
18 gtk
.MESSAGE_QUESTION
, gtk
.BUTTONS_YES_NO
,
19 "Puzzle is open. Are you sure you wish to quit?")
20 if dlg
.run () == gtk
.RESPONSE_NO
:
27 # callback for menu item quit activated event
28 def on_quit_activate (self
, menuitem
):
31 # callback for puzzle grid mouse button release event
32 def on_puzzlegrid_button_press_event (self
, drawarea
, event
):
33 self
.window
.set_focus (drawarea
)
36 # moving the current selection in grid by one up or down
37 def move_selection_updown (self
, step
):
38 # increase or reduce the row by step until an occupied grid is found
40 last_occupied_row
= self
.selected_row
42 self
.selected_row
+= step
43 if self
.selected_row
< 0 or self
.selected_row
>= self
.puzzle
.rows
:
44 self
.selected_row
= last_occupied_row
46 if (self
.puzzle
.data
[self
.selected_row
][self
.selected_col
].occupied_across
is True
47 or self
.puzzle
.data
[self
.selected_row
][self
.selected_col
].occupied_down
is True):
50 # moving the current selection in grid by one across either way
51 def move_selection_across (self
, step
):
52 # increase or reduce the row by step until an occupied grid is found
54 last_occupied_col
= self
.selected_col
56 self
.selected_col
+= step
57 if self
.selected_col
< 0 or self
.selected_col
>= self
.puzzle
.cols
:
58 self
.selected_col
= last_occupied_col
60 if (self
.puzzle
.data
[self
.selected_row
][self
.selected_col
].occupied_across
is True
61 or self
.puzzle
.data
[self
.selected_row
][self
.selected_col
].occupied_down
is True):
64 # callback for puzzle grid key release event
65 def on_puzzlegrid_key_press_event (self
, drawarea
, event
):
66 key
= gtk
.gdk
.keyval_name (event
.keyval
)
68 if event
.state
== gtk
.gdk
.SHIFT_MASK
and key
== "Up":
69 # reduce the row by 1 until you find an occupied grid and not a
71 self
.move_selection_updown (-1)
72 drawarea
.queue_draw ()
73 elif event
.state
== gtk
.gdk
.SHIFT_MASK
and key
== "Down":
74 # increase the row by 1 until you find an occupied grid and not a
76 self
.move_selection_updown (1)
77 drawarea
.queue_draw ()
78 elif event
.state
== gtk
.gdk
.SHIFT_MASK
and key
== "Right":
79 # increase the column by 1 until you find an occupied grid and not
81 self
.move_selection_across (1)
82 drawarea
.queue_draw ()
83 elif event
.state
== gtk
.gdk
.SHIFT_MASK
and key
== "Left":
84 # decrease the column by 1 until you find an occupied grid and not
86 self
.move_selection_across (-1)
87 drawarea
.queue_draw ()
90 # puzzle grid focus in event
91 def on_puzzlegrid_focus_out_event (self
, drawarea
, event
):
92 col
= drawarea
.window
.get_colormap ().alloc_color (gtk
.gdk
.Color ("gray"))
93 drawarea
.window
.set_background (col
)
97 # puzzle grid focus out event
98 def on_puzzlegrid_focus_in_event (self
, drawarea
, event
):
99 col
= drawarea
.window
.get_colormap ().alloc_color (gtk
.gdk
.Color ("white"))
100 drawarea
.window
.set_background (col
)
103 # callback for drawing the puzzle grid
104 def on_puzzlegrid_expose_event (self
, drawarea
, event
):
105 # if puzzle is loaded
108 drawarea
.set_size_request (self
.puzzle
.cols
*30+2, self
.puzzle
.rows
*30+2)
110 #numlayout = gtk.PrintContext().create_pango_layout ()
111 #numlayout.set_font_description (pango.FontDescription ("Sans 8"))
112 ctx
= drawarea
.window
.cairo_create ()
113 ctx
.set_line_width (1.5)
115 # run through the grid
116 for row
in range (self
.puzzle
.rows
):
117 for col
in range (self
.puzzle
.cols
):
118 # (re)set foreground color
119 ctx
.set_source_rgb (0, 0, 0)
120 # if the area is not occupied
121 if (self
.puzzle
.data
[row
][col
].occupied_across
is False and
122 self
.puzzle
.data
[row
][col
].occupied_down
is False):
123 ctx
.rectangle (col
*30, row
*30, 30, 30)
126 # if selected row/column
127 if row
== self
.selected_row
and col
== self
.selected_col
:
128 ctx
.set_source_rgb (1, 1, 0.6)
129 ctx
.rectangle (col
*30,row
*30, 30, 30)
132 ctx
.set_source_rgb (1, 1, 1)
133 ctx
.rectangle (col
*30, row
*30, 30, 30)
135 ctx
.set_source_rgb (0, 0, 0)
136 ctx
.rectangle (col
*30, row
*30, 30, 30)
140 if self
.puzzle
.data
[row
][col
].numbered
<> 0:
141 ctx
.set_source_rgb (0, 0, 0)
142 ctx
.select_font_face ("Sans 7")
143 ctx
.move_to (col
*30+2, row
*30+10)
144 ctx
.show_text (str(self
.puzzle
.data
[row
][col
].numbered
))
148 def load_clues (self
):
149 # get the clues list store objects
150 across
= self
.ui
.get_object ("clues_across")
151 down
= self
.ui
.get_object ("clues_down")
155 # if puzzle is loaded
157 clues_across
= self
.puzzle
.get_clues_across ()
158 clues_down
= self
.puzzle
.get_clues_down ()
159 # insert the numbers and the clues for across
160 for word
, clue
in clues_across
:
161 across
.append ([str(self
.puzzle
.data
[word
[1]][word
[2]].numbered
),
163 # insert the numbers and the clues for down
164 for word
, clue
in clues_down
:
165 down
.append ([ str(self
.puzzle
.data
[word
[1]][word
[2]].numbered
),
168 def open_file (self
, file):
169 # try to open the file
172 self
.puzzle
= cPickle
.load (open (file, "rb"))
173 # assert that it is unfrozen otherwise raise frozen grid exception
174 self
.puzzle
.assert_frozen_grid ()
176 # set selected initial row and column to 0
177 self
.selected_row
= 0
178 self
.selected_col
= 0
179 self
.window
.set_title ("GetAClue player - " + file)
182 # handle unpickling, and file errors
183 except (cPickle
.UnpicklingError
, IOError, OSError):
184 dlg
= gtk
.MessageDialog (self
.window
, gtk
.DIALOG_MODAL
,
185 gtk
.MESSAGE_ERROR
, gtk
.BUTTONS_CLOSE
,
186 "Invalid file. Cannot be loaded")
189 # if the puzzle has no words, then it cannot be played obviously
190 except crosswordpuzzle
.NoWordsException
:
192 dlg
= gtk
.MessageDialog (self
.window
, gtk
.DIALOG_MODAL
,
193 gtk
.MESSAGE_ERROR
, gtk
.BUTTONS_CLOSE
,
194 "Word grid has no words. Cannot play")
197 # if the puzzle is not frozen then it cannot be played
198 except crosswordpuzzle
.FrozenGridException
:
200 dlg
= gtk
.MessageDialog (self
.window
, gtk
.DIALOG_MODAL
,
201 gtk
.MESSAGE_ERROR
, gtk
.BUTTONS_CLOSE
,
202 "Word grid is not finalized/frozen. Cannot play")
206 def __init__ (self
, file_to_play
= None):
207 # load the user interface
208 self
.ui
= gtk
.Builder ()
209 self
.ui
.add_from_file ("playerwindow.glade")
212 self
.window
= self
.ui
.get_object ("mainwindow")
215 # set the cell renderer
216 cell
= gtk
.CellRendererText ()
217 tree_acol1
= self
.ui
.get_object ("tree_clues_across").get_column (0)
218 tree_acol2
= self
.ui
.get_object ("tree_clues_across").get_column (1)
219 tree_acol1
.pack_start (cell
)
220 tree_acol1
.add_attribute (cell
, "text", 0)
221 tree_acol2
.pack_start (cell
)
222 tree_acol2
.add_attribute (cell
, "text", 1)
224 tree_down
= self
.ui
.get_object ("tree_clues_down")
225 tree_dcol1
= self
.ui
.get_object ("tree_clues_down").get_column (0)
226 tree_dcol2
= self
.ui
.get_object ("tree_clues_down").get_column (1)
227 tree_dcol1
.pack_start (cell
)
228 tree_dcol1
.add_attribute (cell
, "text", 0)
229 tree_dcol2
.pack_start (cell
)
230 tree_dcol2
.add_attribute (cell
, "text", 1)
232 # connect the signals
233 self
.ui
.connect_signals (self
)
235 # set the puzzle to None
238 # open the file if it is set
240 self
.open_file (file_to_play
)