~ubuntu-branches/ubuntu/trusty/sugar-sliderpuzzle-activity/trusty

« back to all changes in this revision

Viewing changes to SliderPuzzle.activity/SliderPuzzleUI.py

  • Committer: Bazaar Package Importer
  • Author(s): Jani Monoses
  • Date: 2008-02-16 20:54:56 UTC
  • Revision ID: james.westby@ubuntu.com-20080216205456-yrap5ajfu0qyadf2
Tags: upstream-5
ImportĀ upstreamĀ versionĀ 5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2007 World Wide Workshop Foundation
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
16
#
 
17
# If you find this activity useful or end up using parts of it in one of your
 
18
# own creations we would love to hear from you at info@WorldWideWorkshop.org !
 
19
#
 
20
 
 
21
import pygtk
 
22
pygtk.require('2.0')
 
23
import gtk, gobject, pango
 
24
 
 
25
from mamamedia_modules import utils
 
26
from mamamedia_modules import NotebookReaderWidget
 
27
from mamamedia_modules import BorderFrame, BORDER_ALL_BUT_BOTTOM, BORDER_ALL_BUT_LEFT
 
28
from mamamedia_modules import LanguageComboBox
 
29
from mamamedia_modules import ImageSelectorWidget
 
30
from mamamedia_modules import TimerWidget
 
31
from mamamedia_modules import CategorySelector
 
32
from mamamedia_modules import BuddyPanel
 
33
 
 
34
from mamamedia_modules import GAME_IDLE, GAME_STARTED, GAME_FINISHED, GAME_QUIT
 
35
 
 
36
#from utils import load_image, SliderCreator, GAME_IDLE, GAME_STARTED, GAME_FINISHED, GAME_QUIT, trace
 
37
 
 
38
#from mamamedia_ui import NotebookReaderWidget, BorderFrame, BORDER_ALL_BUT_BOTTOM, BORDER_ALL_BUT_LEFT
 
39
 
 
40
 
 
41
#from toolbar import SliderToolbar
 
42
#from i18n import LanguageComboBox
 
43
import locale
 
44
 
 
45
import logging
 
46
from glob import glob
 
47
from SliderPuzzleWidget import SliderPuzzleWidget
 
48
from time import time
 
49
import os
 
50
import md5
 
51
 
 
52
try:
 
53
    from sugar.activity import activity
 
54
    from sugar.graphics import units
 
55
    _inside_sugar = True
 
56
except:
 
57
    _inside_sugar = False
 
58
 
 
59
 
 
60
SLICE_BTN_WIDTH = 50
 
61
 
 
62
THUMB_SIZE = 48
 
63
IMAGE_SIZE = 200
 
64
#GAME_SIZE = 294
 
65
GAME_SIZE = 574
 
66
 
 
67
#MYOWNPIC_FOLDER = os.path.expanduser("~/.sugar/default/org.worldwideworkshop.olpc.SliderPuzzle.MyOwnPictures")
 
68
# Colors from Rich's UI design
 
69
 
 
70
COLOR_FRAME_OUTER = "#B7B7B7"
 
71
COLOR_FRAME_GAME = "#FF0099"
 
72
COLOR_FRAME_THUMB = COLOR_FRAME_GAME
 
73
COLOR_FRAME_CONTROLS = "#FFFF00"
 
74
COLOR_BG_CONTROLS = "#66CC00"
 
75
COLOR_FG_BUTTONS = (
 
76
    (gtk.STATE_NORMAL,"#CCFF99"),
 
77
    (gtk.STATE_ACTIVE,"#CCFF99"),
 
78
    (gtk.STATE_PRELIGHT,"#CCFF99"),
 
79
    (gtk.STATE_SELECTED,"#CCFF99"),
 
80
    (gtk.STATE_INSENSITIVE,"#CCFF99"),
 
81
    )
 
82
COLOR_BG_BUTTONS = (
 
83
    (gtk.STATE_NORMAL,"#027F01"),
 
84
    (gtk.STATE_ACTIVE,"#014D01"),
 
85
    (gtk.STATE_PRELIGHT,"#016D01"),
 
86
    (gtk.STATE_SELECTED,"#027F01"),
 
87
    (gtk.STATE_INSENSITIVE,"#CCCCCC"),
 
88
    )
 
89
 
 
90
def prepare_btn(btn, w=-1, h=-1):
 
91
    for state, color in COLOR_BG_BUTTONS:
 
92
        btn.modify_bg(state, gtk.gdk.color_parse(color))
 
93
    c = btn.get_child()
 
94
    if c is not None:
 
95
        for state, color in COLOR_FG_BUTTONS:
 
96
            c.modify_fg(state, gtk.gdk.color_parse(color))
 
97
    else:
 
98
        for state, color in COLOR_FG_BUTTONS:
 
99
            btn.modify_fg(state, gtk.gdk.color_parse(color))
 
100
    if w>0 or h>0:
 
101
        btn.set_size_request(w, h)
 
102
    return btn
 
103
 
 
104
 
 
105
class SliderPuzzleUI (gtk.Table):
 
106
    __gsignals__ = {'game-state-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (int,))}
 
107
    
 
108
    def __init__(self, parent):
 
109
        super(SliderPuzzleUI, self).__init__(3,3,False)
 
110
        self._parent = parent
 
111
 
 
112
        # We want the translatables to be detected but not yet translated
 
113
        global _
 
114
        _ = lambda x: x
 
115
        self.labels_to_translate = []
 
116
 
 
117
        self._state = GAME_IDLE
 
118
 
 
119
        inner_table = gtk.Table(2,2,False)
 
120
        self.add(inner_table)
 
121
 
 
122
        self.game = SliderPuzzleWidget(9, GAME_SIZE, GAME_SIZE)
 
123
        self.game.connect("solved", self.do_solve)
 
124
        self.game.connect("moved", self.slider_move_cb)
 
125
        self._parent.connect("key_press_event",self.game.process_key)
 
126
        self._parent.connect("key_press_event",self.process_key)
 
127
        self.game.show()
 
128
        desktop = BorderFrame(border_color=COLOR_FRAME_CONTROLS)
 
129
        desktop.show()
 
130
        desktop.add(self.game)
 
131
        self.game_wrapper = gtk.VBox()
 
132
        self.game_wrapper.show()
 
133
        inner = gtk.HBox()
 
134
        inner.show()
 
135
        #BorderFrame(border=BORDER_ALL_BUT_BOTTOM,
 
136
        #                                border_color=COLOR_FRAME_CONTROLS,
 
137
        #                                bg_color=COLOR_BG_CONTROLS)
 
138
        inner.pack_start(desktop, expand=True, fill=False)
 
139
        self.game_wrapper.pack_start(inner, expand=True, fill=False)
 
140
 
 
141
        # panel is a holder for everything on the left side down to (not inclusive) the language dropdown
 
142
        panel = gtk.VBox()
 
143
        
 
144
        # Logo image
 
145
        img_logo = gtk.Image()
 
146
        img_logo.set_from_file("icons/logo.png")
 
147
        img_logo.show()
 
148
        panel.pack_start(img_logo, expand=False, fill=False)
 
149
 
 
150
        # Control panel has the image controls
 
151
        control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM,
 
152
                                    border_color=COLOR_FRAME_CONTROLS,
 
153
                                    bg_color=COLOR_BG_CONTROLS)
 
154
        control_panel_box = gtk.VBox()
 
155
        control_panel.add(control_panel_box)
 
156
 
 
157
        spacer = gtk.Label()
 
158
        spacer.set_size_request(-1, 5)
 
159
        control_panel_box.pack_start(spacer, expand=False, fill=False)
 
160
 
 
161
        # ...
 
162
 
 
163
        # Slice buttons
 
164
        btn_box = gtk.Table(1,5,False)
 
165
        btn_box.set_col_spacings(5)
 
166
        btn_box.set_row_spacings(5)
 
167
        btn_box.attach(gtk.Label(), 0,1,0,2)
 
168
 
 
169
        #spacer = gtk.Label()
 
170
        #spacer.set_size_request(-1, 15)
 
171
        #control_panel_box.pack_start(spacer, expand=False, fill=False)
 
172
        #cutter = gtk.HBox(False, 8)
 
173
        #cutter.pack_start(gtk.Label(), True)
 
174
        self.btn_9 = prepare_btn(gtk.ToggleButton("9"),SLICE_BTN_WIDTH)
 
175
        self.btn_9.set_active(True)
 
176
        self.btn_9.connect("clicked", self.set_nr_pieces, 9)
 
177
        btn_box.attach(self.btn_9, 1,2,0,1,0,0)
 
178
        #cutter.pack_start(self.btn_9, False, False)
 
179
        self.btn_12 = prepare_btn(gtk.ToggleButton("12"), SLICE_BTN_WIDTH)
 
180
        self.btn_12.connect("clicked", self.set_nr_pieces, 12)
 
181
        btn_box.attach(self.btn_12, 2,3,0,1,0,0)
 
182
        #cutter.pack_start(self.btn_12, False, False)
 
183
        self.btn_16 = prepare_btn(gtk.ToggleButton("16"), SLICE_BTN_WIDTH)
 
184
        self.btn_16.connect("clicked", self.set_nr_pieces, 16)
 
185
        btn_box.attach(self.btn_16, 3,4,0,1,0,0)
 
186
        #cutter.pack_start(self.btn_16, False, False)
 
187
        #cutter.pack_start(gtk.Label(), True)
 
188
        #control_panel_box.pack_start(cutter, True)
 
189
        #spacer = gtk.Label()
 
190
        #spacer.set_size_request(-1, 10)
 
191
        #control_panel_box.pack_start(spacer, False)
 
192
        btn_box.attach(gtk.Label(), 4,5,0,1)
 
193
        control_panel_box.pack_start(btn_box, expand=False)
 
194
 
 
195
 
 
196
 
 
197
 
 
198
 
 
199
        self.thumb = ImageSelectorWidget(frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, image_dir='images')
 
200
        self.thumb.connect("category_press", self.do_select_category)
 
201
        self.thumb.connect("image_press", self.set_nr_pieces)
 
202
        control_panel_box.pack_start(self.thumb, False)
 
203
 
 
204
        spacer = gtk.Label()
 
205
        spacer.set_size_request(-1, 5)
 
206
        control_panel_box.pack_start(spacer, expand=False, fill=False)
 
207
 
 
208
        # The game control buttons
 
209
        btn_box = gtk.Table(3,3,False)
 
210
        btn_box.set_row_spacings(2)
 
211
        btn_box.attach(gtk.Label(), 0,1,0,3)
 
212
        btn_box.attach(gtk.Label(), 2,3,0,3)
 
213
        self.btn_solve = prepare_btn(gtk.Button(" "), 200)
 
214
        self.labels_to_translate.append([self.btn_solve, _("Solve")])
 
215
        self.btn_solve.connect("clicked", self.do_solve)
 
216
        btn_box.attach(self.btn_solve, 1,2,0,1,0,0)
 
217
        self.btn_shuffle = prepare_btn(gtk.Button(" "), 200)
 
218
        self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")])
 
219
        self.btn_shuffle.connect("clicked", self.do_shuffle)
 
220
        btn_box.attach(self.btn_shuffle, 1,2,1,2,0,0)
 
221
        self.btn_add = prepare_btn(gtk.Button(" "), 200)
 
222
        self.labels_to_translate.append([self.btn_add, _("My Picture")])
 
223
        self.btn_add.connect("clicked", self.do_add_image)
 
224
        btn_box.attach(self.btn_add, 1,2,2,3,0,0)
 
225
        control_panel_box.pack_start(btn_box, False)
 
226
 
 
227
        # Control panel end
 
228
        panel.pack_start(control_panel, expand=True, fill=True)
 
229
 
 
230
        inner_table.attach(panel, 0,1,0,1,0)
 
231
 
 
232
        self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME)
 
233
        self.game_box.add(self.game_wrapper)
 
234
        inner_table.attach(self.game_box, 1,2,0,1, gtk.FILL, gtk.FILL)
 
235
 
 
236
        lang_combo = prepare_btn(LanguageComboBox('org.worldwideworkshop.olpc.SliderPuzzle'))
 
237
        lang_combo.connect('changed', self.do_select_language)
 
238
        # Push the gettext translator into the global namespace
 
239
        del _
 
240
        lang_combo.install()
 
241
        lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS,
 
242
                               border_color=COLOR_FRAME_CONTROLS)
 
243
        hbox = gtk.HBox(False)
 
244
        vbox = gtk.VBox(False)
 
245
        vbox.pack_start(lang_combo, padding=8)
 
246
        hbox.pack_start(vbox, padding=8)
 
247
        lang_box.add(hbox)
 
248
        inner_table.attach(lang_box, 0,1,1,2,gtk.FILL, gtk.FILL)
 
249
 
 
250
        timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT,
 
251
                                bg_color=COLOR_BG_CONTROLS,
 
252
                                border_color=COLOR_FRAME_CONTROLS)
 
253
        timer_hbox = gtk.HBox(False)
 
254
        self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1],
 
255
                                 fg_color=COLOR_FG_BUTTONS[0][1],
 
256
                                 lbl_color=COLOR_BG_BUTTONS[1][1])
 
257
        self.timer.set_sensitive(False)
 
258
        self.timer.set_border_width(3)
 
259
        self.labels_to_translate.append((self.timer, _("Time: ")))
 
260
        timer_hbox.pack_start(self.timer, False, padding=8)
 
261
        self.timer.connect('timer_toggle', self.timer_toggle_cb)
 
262
 
 
263
        self.msg_label = gtk.Label()
 
264
        self.msg_label.show()
 
265
        timer_hbox.pack_start(self.msg_label, True)
 
266
        
 
267
        self.btn_lesson = prepare_btn(gtk.Button(" "))
 
268
        self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")])
 
269
        self.btn_lesson.connect("clicked", self.do_lesson_plan)
 
270
        timer_hbox.pack_start(self.btn_lesson, False, padding=8)
 
271
        vbox = gtk.VBox(False)
 
272
        vbox.pack_start(timer_hbox, padding=8)
 
273
        timer_box.add(vbox)
 
274
        inner_table.attach(timer_box, 1,2,1,2,gtk.FILL|gtk.EXPAND, gtk.FILL)
 
275
        #panel.pack_start(lang_box, expand=False, fill=False)
 
276
 
 
277
        self.do_select_language(lang_combo)
 
278
        
 
279
        self.buddy_panel = BuddyPanel()
 
280
        self.buddy_panel.show()
 
281
 
 
282
        if not parent._shared_activity:
 
283
            self.do_select_category(self)
 
284
        else:
 
285
            self.set_message(_("Waiting for remote game..."))
 
286
 
 
287
        # Contest mode flags
 
288
        self.set_contest_mode(False)
 
289
 
 
290
        self._on_lesson_plan = False
 
291
 
 
292
    def set_message (self, msg, frommesh=False):
 
293
        if frommesh and self.get_game_state() < GAME_STARTED:
 
294
            return
 
295
        self.msg_label.set_label(msg)
 
296
 
 
297
    def is_initiator (self):
 
298
        return self._parent.initiating
 
299
 
 
300
    def set_readonly (self, ro=True):
 
301
        self.thumb.set_readonly(ro)
 
302
        for b in (self.btn_9, self.btn_12, self.btn_16):
 
303
            if not b.get_active():
 
304
                b.set_sensitive(False)
 
305
 
 
306
    @utils.trace
 
307
    def timer_toggle_cb (self, evt, running):
 
308
        logging.debug("Timer running: %s" % str(running))
 
309
        if self._contest_mode and running:
 
310
            self.set_game_state(GAME_STARTED)
 
311
        self._send_status_update()
 
312
        #if self._contest_mode:
 
313
        #    if running:
 
314
        #        if self.game.filename and not self.game_wrapper.get_parent():
 
315
        #            self.game_box.pop()
 
316
        #    else:
 
317
        #        if not self.buddy_panel.get_parent():
 
318
        #            self.game_box.push(self.buddy_panel)
 
319
 
 
320
    def _set_control_area (self, *args):
 
321
        """ The controls area below the logo needs different actions when in contest mode,
 
322
        and also if we are the contest initiators or not. """
 
323
        if self._contest_mode:
 
324
            if self.get_game_state() > GAME_IDLE:
 
325
                self.set_readonly()
 
326
            else:
 
327
                if self.is_initiator():
 
328
                    if self.timer.is_reset():
 
329
                        self.set_message(_("Select image and press Start Game..."))
 
330
                    else:
 
331
                        self.set_game_state(GAME_STARTED)
 
332
                else:
 
333
                    self.set_message(_("Waiting for Puzzle image to be chosen..."))
 
334
                    self.set_button_translation(self.btn_add, "Buddies")
 
335
                    self.btn_add.get_child().set_label(_("Buddies"))
 
336
 
 
337
    def set_game_state (self, state, force=False):
 
338
        if state[0] > self._state[0] or force:
 
339
            self._state = state
 
340
            self.emit('game-state-changed', state[0])
 
341
            self._set_control_area()
 
342
            if state == GAME_STARTED:
 
343
                self.set_button_translation(self.btn_add, "Buddies")
 
344
                self.btn_add.get_child().set_label(_("Buddies"))
 
345
            self._send_status_update()
 
346
 
 
347
    def get_game_state (self):
 
348
        return self._state
 
349
 
 
350
    def set_button_translation (self, btn, translation):
 
351
        for i in range(len(self.labels_to_translate)):
 
352
            if self.labels_to_translate[i][0] == btn:
 
353
                self.labels_to_translate[i][1] = translation
 
354
                break
 
355
 
 
356
    def set_contest_mode (self, mode):
 
357
        if getattr(self, '_contest_mode', None) != mode:
 
358
            self._contest_mode = bool(mode)
 
359
            self._set_control_area()
 
360
            if self._contest_mode:
 
361
                self.set_button_translation(self.btn_solve, "Give Up")
 
362
                self.btn_solve.get_child().set_label(_("Give Up"))
 
363
                self.set_button_translation(self.btn_shuffle, "Start Game")
 
364
                self.btn_shuffle.get_child().set_label(_("Start Game"))
 
365
        
 
366
    def is_contest_mode (self):
 
367
        return self._contest_mode# and self.game.filename
 
368
 
 
369
    def do_select_language (self, combo, *args):
 
370
        self.selected_lang_details = combo.translations[combo.get_active()]
 
371
        self.refresh_labels()
 
372
 
 
373
    def refresh_labels (self, first_time=False):
 
374
        self._parent.set_title(_("Slider Puzzle Activity"))
 
375
        for lbl in self.labels_to_translate:
 
376
            if isinstance(lbl[0], gtk.Button):
 
377
                lbl[0].get_child().set_label(_(lbl[1]))
 
378
            else:
 
379
                lbl[0].set_label(_(lbl[1]))
 
380
        if not self.game_wrapper.get_parent() and not first_time:
 
381
            self.game_box.pop()
 
382
            if isinstance(self.game_box.get_child(), NotebookReaderWidget):
 
383
                m = self.do_lesson_plan
 
384
            else:
 
385
                m = self.do_select_category
 
386
            m(self)
 
387
 
 
388
    @utils.trace
 
389
    def set_nr_pieces (self, btn, nr_pieces=None):
 
390
        #if isinstance(btn, gtk.ToggleButton) and not btn.get_active():
 
391
        #    return
 
392
        if self.is_contest_mode() and isinstance(btn, gtk.ToggleButton) and nr_pieces == self.game.get_nr_pieces():
 
393
            return
 
394
        if isinstance(btn, gtk.ToggleButton):
 
395
            if not btn.get_active():
 
396
                if nr_pieces == self.game.get_nr_pieces():
 
397
                    print "A"
 
398
                    btn.set_active(True)
 
399
                return
 
400
        if nr_pieces is None:
 
401
            nr_pieces = self.game.get_nr_pieces()
 
402
        if btn is None: #not isinstance(btn, gtk.ToggleButton):
 
403
            if self._contest_mode:
 
404
                self.set_game_state(GAME_STARTED)
 
405
            for n, b in ((9, self.btn_9),(12, self.btn_12),(16, self.btn_16)):
 
406
                if n == nr_pieces and not b.get_active():
 
407
                    print "B"
 
408
                    b.set_sensitive(True)
 
409
                    b.set_active(True)
 
410
                    return
 
411
        if self.thumb.has_image():
 
412
            if not self.game_wrapper.get_parent():
 
413
                self.game_box.pop()
 
414
            self.game.load_image(self.thumb.get_image())
 
415
            #self.thumb.set_game_widget(self.game)
 
416
        self.game.set_nr_pieces(nr_pieces)
 
417
        self.timer.reset(False)
 
418
        if isinstance(btn, gtk.ToggleButton):
 
419
            for n, b in ((9, self.btn_9),(12, self.btn_12),(16, self.btn_16)):
 
420
                if b is not btn:
 
421
                    print "C"
 
422
                    b.set_active(False)
 
423
                    b.set_sensitive(not self._contest_mode)
 
424
 
 
425
    def do_shuffle (self, *args, **kwargs):
 
426
        if self._contest_mode:
 
427
            if self.get_game_state() > GAME_IDLE:
 
428
                # Restart
 
429
                self.set_game_state(GAME_STARTED, True)
 
430
                self._parent.frozen.thaw()
 
431
                self.timer.reset(True)
 
432
            elif self.game.filename is not None and self.timer.is_reset():
 
433
                # Start
 
434
                self.timer.start()
 
435
        elif self.thumb.has_image():
 
436
            if not self.game_wrapper.get_parent():
 
437
                self.game_box.pop()
 
438
            self.game.load_image(self.thumb.get_image())
 
439
            #self.thumb.set_game_widget(self.game)
 
440
            self.game.randomize()
 
441
            self.timer.reset(False)
 
442
 
 
443
    def slider_move_cb (self, *args):
 
444
        if not self.timer.is_running():
 
445
            self.timer.start()
 
446
        
 
447
    def do_solve (self, btn):
 
448
        if self.game.filename is not None:
 
449
            if not self.game_wrapper.get_parent():
 
450
                self.game_box.pop()
 
451
            self.game.show_image()
 
452
            self.timer.stop(True)
 
453
            if self._contest_mode and self.get_game_state() == GAME_STARTED:
 
454
                if btn != self.btn_solve:
 
455
                    self.set_game_state(GAME_FINISHED)
 
456
                    self.set_message(_("Puzzle Solved!"))
 
457
                else:
 
458
                    self.set_game_state(GAME_QUIT)
 
459
                    self.set_message(_("Gave Up"))
 
460
        self._set_control_area()
 
461
 
 
462
#    @utils.trace
 
463
#    def do_select_category(self, owner, *args, **kwargs):
 
464
#        if isinstance(owner, CategorySelector):
 
465
#            self.thumb.set_image_dir(args[0])
 
466
#            #self.game_box.pop()
 
467
#            if not self.thumb.category.has_images():
 
468
#                self.do_add_image(None)
 
469
#        else:
 
470
#            if self.game_wrapper.get_parent():
 
471
#                s = CategorySelector("images", _("Choose a Subject"), self.thumb.get_image_dir())
 
472
#                s.connect("selected", self.do_select_category)
 
473
#                s.show()
 
474
#                self.game_box.push(s)
 
475
#                s.grab_focus()
 
476
#            else:
 
477
#                self.game_box.pop()
 
478
 
 
479
    def do_select_category (self, o, *args):
 
480
        if isinstance(o, CategorySelector):
 
481
            self.thumb.set_image_dir(args[0])
 
482
            #if not self.thumb.category.has_images():
 
483
            #    self.do_add_image(None)
 
484
        else:
 
485
            if self.game_wrapper.get_parent():
 
486
                print ("Current cat dir=", self.thumb.get_image_dir())
 
487
                s = CategorySelector(_("Choose a Subject"),
 
488
                                     self.thumb.get_image_dir(),
 
489
                                     path="images")
 
490
                                     #extra=('images/Sequencing Puzzles',))
 
491
                s.connect("selected", self.do_select_category)
 
492
                s.show()
 
493
                self.game_box.push(s)
 
494
                s.grab_focus()
 
495
            else:
 
496
                self.game_box.pop()
 
497
 
 
498
    @utils.trace
 
499
    def do_add_image (self, widget, *args):
 
500
        """ Use to trigger and process the My Own Image selector.
 
501
        Also used for showing the buddies panel on contest mode"""
 
502
        if self._contest_mode and self.get_game_state() >= GAME_STARTED:
 
503
            # Buddy Panel
 
504
            if not self.buddy_panel.get_parent():
 
505
                self.timer.stop()
 
506
                self.game_box.push(self.buddy_panel)
 
507
            else:
 
508
                self.game_box.pop()
 
509
        elif self._contest_mode and not self.is_initiator():
 
510
            # do nothing
 
511
            pass
 
512
        else:
 
513
            self.thumb.add_image()
 
514
            self.do_shuffle()
 
515
            
 
516
        #if response is None:
 
517
        #    else:
 
518
        #        # My Own Image selector
 
519
        #        imgfilter = gtk.FileFilter()
 
520
        #        imgfilter.set_name(_("Image Files"))
 
521
        #        imgfilter.add_mime_type('image/*')
 
522
        #        fd = gtk.FileChooserDialog(title=_("Select Image File"), parent=self._parent,
 
523
        #                                   action=gtk.FILE_CHOOSER_ACTION_OPEN,
 
524
        #                                   buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
 
525
        #
 
526
        #        fd.set_current_folder(os.path.expanduser("~/"))
 
527
        #        fd.set_modal(True)
 
528
        #        fd.add_filter(imgfilter)
 
529
        #        fd.connect("response", self.do_add_image)
 
530
        #        fd.resize(800,600)
 
531
        #        fd.show()
 
532
        #else:
 
533
        #    if response == gtk.RESPONSE_ACCEPT:
 
534
        #        if self.thumb.load_image(widget.get_filename()):
 
535
        #            self.do_shuffle()
 
536
        #        else:
 
537
        #            err = gtk.MessageDialog(self._parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
 
538
        #                                    _("Not a valid image file"))
 
539
        #            err.run()
 
540
        #            err.destroy()
 
541
        #            return
 
542
        #    widget.destroy()
 
543
 
 
544
    def do_lesson_plan (self, btn):
 
545
        if self._on_lesson_plan:
 
546
            return
 
547
        try:
 
548
            self._on_lesson_plan = True
 
549
            if self._contest_mode and self.get_game_state() < GAME_STARTED:
 
550
                return
 
551
            if isinstance(self.game_box.get_child(), NotebookReaderWidget):
 
552
                if self.game_box.get_child().loaded:
 
553
                    self.game_box.pop()
 
554
            else:
 
555
                s = NotebookReaderWidget('lessons', self.selected_lang_details)
 
556
                s.connect('parent-set', self.do_lesson_plan_reparent)
 
557
                s.show_all()
 
558
                self.game_box.push(s)
 
559
                self.timer.stop()
 
560
        finally:
 
561
            self._on_lesson_plan = False
 
562
 
 
563
    def do_lesson_plan_reparent (self, widget, oldparent):
 
564
        if widget.parent is None:
 
565
            self.set_button_translation(self.btn_lesson, "Lesson Plans")
 
566
            self.btn_lesson.get_child().set_label(_("Lesson Plans"))
 
567
        else:
 
568
            self.set_button_translation(self.btn_lesson, "Close Lesson")
 
569
            self.btn_lesson.get_child().set_label(_("Close Lesson"))
 
570
 
 
571
    def process_key (self, w, e):
 
572
        """ The callback for key processing. The button shortcuts are all defined here. """
 
573
        k = gtk.gdk.keyval_name(e.keyval)
 
574
        if not isinstance(self._parent.get_focus(), gtk.Editable):
 
575
            if k == '1':
 
576
                self.btn_9.clicked()
 
577
                return True
 
578
            if k == '2':
 
579
                self.btn_12.clicked()
 
580
                return True
 
581
            if k == '3':
 
582
                self.btn_16.clicked()
 
583
                return True
 
584
            if k == 'period':
 
585
                self.thumb.next()
 
586
                return True
 
587
            if k == 'comma':
 
588
                self.thumb.previous()
 
589
                return True
 
590
            if k == 'Return':
 
591
                self.set_nr_pieces(None)
 
592
                return True
 
593
            if k == 'slash':
 
594
                self.do_select_category(None)
 
595
                return True
 
596
            if k == 'question':
 
597
                self.btn_add.clicked()
 
598
                return True
 
599
            if k == 'equal':
 
600
                self.btn_solve.clicked()
 
601
                return True
 
602
            if k in ('Escape', 'q'):
 
603
                gtk.main_quit()
 
604
                return True
 
605
        return False
 
606
 
 
607
    @utils.trace
 
608
    def _freeze (self, journal=True):
 
609
        """ returns a json writable object representation capable of being used to restore our current status """
 
610
        return (self.thumb._freeze(), self.game._freeze(journal=journal), self.game.get_nr_pieces(), self.timer._freeze())
 
611
 
 
612
    def _thaw (self, obj):
 
613
        """ retrieves a frozen status from a python object, as per _freeze """
 
614
        #self.thumb._thaw(obj[0])
 
615
        if not obj[1].has_key('image'):
 
616
            self.game.load_image(self.thumb.get_image())
 
617
        self.set_nr_pieces(None, obj[2])
 
618
        print obj[1].keys()
 
619
        wimg = obj[1].has_key('image')
 
620
        self.game._thaw(obj[1])
 
621
        if wimg:
 
622
            print "Forcing thumb image from the one in game"
 
623
            self.thumb.load_pb(self.game.image)
 
624
        self.timer._thaw(obj[3])
 
625
        self.game_box.pop()
 
626
        
 
627
    @utils.trace
 
628
    def _send_status_update (self):
 
629
        """ Send a status update signal """
 
630
        if self._parent._shared_activity:
 
631
            if self.get_game_state() == GAME_STARTED:
 
632
                if self.thumb.has_image():
 
633
                    self.set_message(_("Game Started!"))
 
634
            self._parent.game_tube.StatusUpdate(self._state[1], self.timer.is_running(), self.timer.ellapsed())
 
635
 
 
636
def main():
 
637
    win = gtk.Window(gtk.WINDOW_TOPLEVEL)
 
638
    t = SliderPuzzleUI(win)
 
639
    gtk.main()
 
640
    return 0
 
641
 
 
642
if __name__ == "__main__":
 
643
        main()