class JigsawPuzzleUI(BorderFrame): __gsignals__ = { 'game-state-changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (int, )) } def __init__(self, parent): super(JigsawPuzzleUI, self).__init__(border_color=COLOR_FRAME_OUTER) self._shuffling = False self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE self._readonly = False self._join_time = 0 inner_table = gtk.Table(2, 2, False) self.add(inner_table) self.game = JigsawPuzzleWidget() self.game.connect('picked', self.piece_pick_cb, False) self.game.connect('dropped', self.piece_drop_cb) self.game.connect('solved', self.do_solve) self.game.connect('cutter-changed', self.cutter_change_cb) self.game.show() # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = gtk.VBox() # Logo image img_logo = gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, expand=False, fill=False) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = gtk.VBox() scrolled = gtk.ScrolledWindow() scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC scrolled.show() scrolled.add_with_viewport(control_panel_box) scrolled.child.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(COLOR_BG_CONTROLS)) control_panel.add(scrolled) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) btn_box = gtk.Table(2, 5, False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) btn_box.attach(gtk.Label(), 0, 1, 0, 2) # Cut type buttons self.btn_basic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'cut_basic.svg'))) self.btn_basic_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_basic_cut), 1, 2, 0, 1, 0, 0) self.btn_simple_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'cut_simple.svg'))) self.btn_simple_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_simple_cut), 2, 3, 0, 1, 0, 0) self.btn_classic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'cut_classic.svg'))) self.btn_classic_cut.set_image(i) # Link cutter buttons with cutter styles self.btn_cut_mapping = { 'basic': self.btn_basic_cut, 'simple': self.btn_simple_cut, 'classic': self.btn_classic_cut, } for k, v in self.btn_cut_mapping.items(): v.connect("released", self.set_piece_cut, k) btn_box.attach(prepare_btn(self.btn_classic_cut), 3, 4, 0, 1, 0, 0) # Difficulty level buttons self.btn_easy_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'level_easy.svg'))) self.btn_easy_level.set_active(True) self.btn_easy_level.set_image(i) btn_box.attach(prepare_btn(self.btn_easy_level), 1, 2, 1, 2, 0, 0) self.btn_normal_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'level_normal.svg'))) self.btn_normal_level.set_image(i) btn_box.attach(prepare_btn(self.btn_normal_level), 2, 3, 1, 2, 0, 0) self.btn_hard_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'level_hard.svg'))) self.btn_hard_level.set_image(i) # Link level buttons with levels self.btn_level_mapping = { 3: self.btn_easy_level, 5: self.btn_normal_level, 8: self.btn_hard_level, } for k, v in self.btn_level_mapping.items(): v.connect("released", self.set_level, k) btn_box.attach(prepare_btn(self.btn_hard_level), 3, 4, 1, 2, 0, 0) btn_box.attach(gtk.Label(), 4, 5, 0, 2) control_panel_box.pack_start(btn_box, expand=False) self.thumb = ImageSelectorWidget(frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, method=utils.RESIZE_PAD, image_dir="images", parent=self._parent) self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.do_shuffle) control_panel_box.pack_start(self.thumb, expand=False) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # The game control buttons btn_box = gtk.Table(3, 4, False) btn_box.set_row_spacings(2) btn_box.attach(gtk.Label(), 0, 1, 0, 4) btn_box.attach(gtk.Label(), 2, 3, 0, 4) self.btn_solve = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1, 2, 0, 1, 0, 0) self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1, 2, 1, 2, 0, 0) self.btn_add = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1, 2, 2, 3, 0, 0) self.btn_hint = prepare_btn(gtk.ToggleButton(" "), 200) self.labels_to_translate.append([self.btn_hint, _("Board Hint")]) self.btn_hint.connect("clicked", self.do_show_hint) btn_box.attach(self.btn_hint, 1, 2, 3, 4, 0, 0) control_panel_box.pack_start(btn_box, False) self.control_panel_box = control_panel_box # Control panel end panel.pack_start(control_panel, expand=True, fill=True) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game) self.notebook = gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box) inner_table.attach(self.notebook, 1, 2, 0, 1) lang_combo = prepare_btn( LanguageComboBox('org.worldwideworkshop.olpc.JigsawPuzzle')) lang_combo.connect('changed', self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = gtk.HBox(False) vbox = gtk.VBox(False) vbox.pack_start(lang_combo, padding=8) hbox.pack_start(vbox, padding=8) lang_box.add(hbox) inner_table.attach(lang_box, 0, 1, 1, 2, gtk.FILL, gtk.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, padding=8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel(BUDDYMODE_COLLABORATION) self.buddy_panel.show() if not parent._shared_activity: self.do_select_category(self) self.set_contest_mode(False) # Assert consistent state self.cutter_change_cb(None, self.game.get_cutter(), self.game.get_target_pieces_per_line()) def set_message(self, msg, frommesh=False): if frommesh and self.get_game_state() != GAME_STARTED: return self.msg_label.set_label(msg) def _set_control_area(self, *args): """ The controls area below the logo needs different actions when in contest mode, and also if we are the contest initiators or not. """ if self._contest_mode: if self.get_game_state() > GAME_IDLE or not self.is_initiator(): self.set_readonly() if self.get_game_state() <= GAME_IDLE: if self.is_initiator(): if self.timer.is_reset(): self.set_message( _("Select image and press Start Game...")) else: self.set_game_state(GAME_STARTED) else: self.set_message( _("Waiting for Puzzle image to be chosen...")) self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) def set_readonly(self): """ In collaborative mode, after an image is selected and the game started you can not change much """ self.thumb.set_readonly(True) self.set_button_translation(self.btn_shuffle, "Game Running") self.btn_shuffle.get_child().set_label(_("Game Running")) self.btn_shuffle.set_sensitive(False) for b in self.btn_cut_mapping.values() + self.btn_level_mapping.values( ): if not (b.get_active() and self.is_initiator()): b.set_sensitive(False) self._readonly = True def is_readonly(self): return self._readonly def is_initiator(self): return self._parent.initiating @utils.trace def timer_toggle_cb(self, evt, running): logging.debug("Timer running: %s" % str(running)) if self._contest_mode and running: self.set_game_state(GAME_STARTED) self._send_status_update() def set_contest_mode(self, mode): if getattr(self, '_contest_mode', None) != mode: self.timer.set_can_stop(not bool(mode)) self._contest_mode = bool(mode) self._set_control_area() if self._contest_mode: self.btn_solve.set_sensitive(False) #self.set_button_translation(self.btn_solve, "Give Up") #self.btn_solve.get_child().set_label(_("Give Up")) self.set_button_translation(self.btn_shuffle, "Start Game") self.btn_shuffle.get_child().set_label(_("Start Game")) @utils.trace def set_game_state(self, state, force=False): if state[0] > self._state[0] or force: self._state = state self.emit('game-state-changed', state[0]) self._set_control_area() if state == GAME_STARTED: self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) if self._contest_mode: if self.is_initiator(): self._send_game_update() self._send_status_update() elif state[0] <= GAME_STARTED[ 0] and self._contest_mode and not self.is_initiator(): c = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(c) def get_game_state(self): return self._state def do_select_category(self, o, *args): if isinstance(o, CategorySelector): self.thumb.set_image_dir(args[0]) #if not self.thumb.category.has_images(): # self.do_add_image(None) else: if self.game.get_parent(): s = CategorySelector(_("Choose a Subject"), self.thumb.get_image_dir(), path="images") s.connect("selected", self.do_select_category) s.show() self.game_box.push(s) s.grab_focus() else: self.game_box.pop() @utils.trace def _show_game(self, pixbuf=None, reshuffle=True): if not self.game.get_parent(): self.game_box.pop() while gtk.events_pending(): gtk.main_iteration(False) c = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(c) if not self.game.prepare_image(pixbuf, reshuffle): self._shuffling = False return self._shuffling = False self.window.set_cursor(None) #self.game.randomize() def do_shuffle(self, o, *args): #if self.thumb.has_image(): # print ("FN", self.thumb.category.filename) if self._contest_mode and \ self.get_game_state() == GAME_IDLE and \ self.game.is_running() and \ o == self.btn_shuffle and \ self.timer.is_reset(): # Start logging.debug('do_shuffle') self.timer.start() elif self.thumb.has_image(): if not self._shuffling: logging.debug('do_shuffle start') self.timer.stop() self._shuffling = True self._show_game(self.thumb.get_image()) self.timer.reset(False) self.do_show_hint(self.btn_hint) def do_solve(self, o, *args): if not self.game.is_running(): return if not self.game.get_parent(): self.game_box.pop() self.game.solve() self.timer.stop(True) if self._contest_mode: self.set_game_state(GAME_FINISHED) self.set_message(_("Puzzle Solved!")) self.control_panel_box.foreach(self.control_panel_box.remove) lbl = gtk.Label(_("Press Stop on the Toolbar to Exit Activity!")) lbl.modify_font(pango.FontDescription("bold 9")) lbl.set_line_wrap(True) lbl.set_justify(gtk.JUSTIFY_CENTER) lbl.set_size_request(200, -1) lbl.show() self.control_panel_box.pack_start(lbl, True) def do_add_image(self, o, *args): if self._contest_mode and self.get_game_state() >= GAME_STARTED: # Buddy Panel if not self.buddy_panel.get_parent(): #self.timer.stop() self.game_box.push(self.buddy_panel) else: self.game_box.pop() else: self.thumb.add_image() @utils.trace def do_select_language(self, combo, *args): self.selected_lang_details = combo.translations[combo.get_active()] self.refresh_labels() def do_show_hint(self, o, *args): self.game.show_hint(o.get_active()) def set_button_translation(self, btn, translation): for i in range(len(self.labels_to_translate)): if self.labels_to_translate[i][0] == btn: self.labels_to_translate[i][1] = translation break def refresh_labels(self, first_time=False): self._parent.set_title(_("Jigsaw Puzzle Activity")) for lbl in self.labels_to_translate: if isinstance(lbl[0], gtk.Button): lbl[0].get_child().set_label(_(lbl[1])) else: lbl[0].set_label(_(lbl[1])) if not self.game.get_parent() and not first_time: self.game_box.pop() if self.notebook.get_current_page() == 1: m = self.do_lesson_plan else: m = self.do_select_category m(self) def set_piece_cut(self, btn, cutter, *args): if self.is_readonly(): return self.game.set_cutter(cutter) if self.game.is_running(): self.do_shuffle(btn) def cutter_change_cb(self, o, cutter, tppl): # tppl = target pieces per line for c, b in self.btn_cut_mapping.items(): if c == cutter: b.set_sensitive(True) b.set_active(True) else: b.set_active(False) for c, b in self.btn_level_mapping.items(): if c == tppl: b.set_sensitive(True) b.set_active(True) else: b.set_active(False) def set_level(self, btn, level, *args): if self.is_readonly(): return self.game.set_target_pieces_per_line(level) if self.game.is_running(): self.do_shuffle(btn) def piece_pick_cb(self, o, piece, from_mesh=False): if not self.timer.is_running(): self.timer.start() if not from_mesh: self._send_pick_notification(piece) def piece_drop_cb(self, o, piece, from_mesh=False): if self._parent._shared_activity and not from_mesh: self._send_drop_notification(piece) def _freeze(self, journal=True): if journal: return { 'thumb': self.thumb._freeze(), 'timer': self.timer._freeze(), 'game': self.game._freeze(), } else: return { 'timer': self.timer._freeze(), 'game': self.game._freeze(img_cksum_only=True), } def _thaw(self, data): self.timer.reset() for k in ('thumb', 'timer', 'game'): if data.has_key(k): logging.debug('_thaw data for %s: %s' % (k, data)) getattr(self, k)._thaw(data[k]) if data.has_key('game'): # and not data.has_key('thumb'): self.thumb.load_pb(self.game.board.cutboard.pb) if data.has_key('timer'): self._join_time = self.timer.ellapsed() if data.has_key('game') and data['game']['piece_pos']: self._show_game(reshuffle=False) @utils.trace def _send_status_update(self): """ Send a status update signal """ if self._parent._shared_activity: if self.get_game_state() == GAME_STARTED: if self.thumb.has_image(): self.set_message(_("Game Started!")) else: self.set_message( _("Waiting for Puzzle image to be transferred...")) self._parent.game_tube.StatusUpdate(self._state[1], self._join_time) @utils.trace def _send_game_update(self): """ A puzzle was selected, share it """ if self._parent._shared_activity: # TODO: Send image self._parent.game_tube.GameUpdate(self._state[1]) @utils.trace def _send_pick_notification(self, piece): """ """ if self._parent._shared_activity: self._parent.game_tube.PiecePicked(piece.get_index()) @utils.trace def _recv_pick_notification(self, index): for piece in self.game.get_floating_pieces(): if piece.get_index() == index: logging.debug("Remote picked piece %s" % piece) piece.set_sensitive(False) @utils.trace def _send_drop_notification(self, piece): """ """ if piece.placed: self._parent.game_tube.PiecePlaced(piece.get_index()) else: self._parent.game_tube.PieceDropped(piece.get_index(), piece.get_position()) @utils.trace def _recv_drop_notification(self, index, position=None): for piece in self.game.get_floating_pieces(): if piece.get_index() == index: logging.debug("Moving piece %s" % piece) if position is None: self.game.board.place_piece(piece) else: self.game._move_cb(piece, position[0], position[1], absolute=True) self.game._drop_cb(piece, from_mesh=True) piece.set_sensitive(True) break
def __init__(self, parent): super(JigsawPuzzleUI, self).__init__(border_color=COLOR_FRAME_OUTER) self._shuffling = False self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE self._readonly = False self._join_time = 0 inner_table = gtk.Table(2, 2, False) self.add(inner_table) self.game = JigsawPuzzleWidget() self.game.connect('picked', self.piece_pick_cb, False) self.game.connect('dropped', self.piece_drop_cb) self.game.connect('solved', self.do_solve) self.game.connect('cutter-changed', self.cutter_change_cb) self.game.show() # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = gtk.VBox() # Logo image img_logo = gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, expand=False, fill=False) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = gtk.VBox() scrolled = gtk.ScrolledWindow() scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC scrolled.show() scrolled.add_with_viewport(control_panel_box) scrolled.child.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(COLOR_BG_CONTROLS)) control_panel.add(scrolled) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) btn_box = gtk.Table(2, 5, False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) btn_box.attach(gtk.Label(), 0, 1, 0, 2) # Cut type buttons self.btn_basic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'cut_basic.svg'))) self.btn_basic_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_basic_cut), 1, 2, 0, 1, 0, 0) self.btn_simple_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'cut_simple.svg'))) self.btn_simple_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_simple_cut), 2, 3, 0, 1, 0, 0) self.btn_classic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'cut_classic.svg'))) self.btn_classic_cut.set_image(i) # Link cutter buttons with cutter styles self.btn_cut_mapping = { 'basic': self.btn_basic_cut, 'simple': self.btn_simple_cut, 'classic': self.btn_classic_cut, } for k, v in self.btn_cut_mapping.items(): v.connect("released", self.set_piece_cut, k) btn_box.attach(prepare_btn(self.btn_classic_cut), 3, 4, 0, 1, 0, 0) # Difficulty level buttons self.btn_easy_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'level_easy.svg'))) self.btn_easy_level.set_active(True) self.btn_easy_level.set_image(i) btn_box.attach(prepare_btn(self.btn_easy_level), 1, 2, 1, 2, 0, 0) self.btn_normal_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'level_normal.svg'))) self.btn_normal_level.set_image(i) btn_box.attach(prepare_btn(self.btn_normal_level), 2, 3, 1, 2, 0, 0) self.btn_hard_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf( utils.load_image(os.path.join('icons', 'level_hard.svg'))) self.btn_hard_level.set_image(i) # Link level buttons with levels self.btn_level_mapping = { 3: self.btn_easy_level, 5: self.btn_normal_level, 8: self.btn_hard_level, } for k, v in self.btn_level_mapping.items(): v.connect("released", self.set_level, k) btn_box.attach(prepare_btn(self.btn_hard_level), 3, 4, 1, 2, 0, 0) btn_box.attach(gtk.Label(), 4, 5, 0, 2) control_panel_box.pack_start(btn_box, expand=False) self.thumb = ImageSelectorWidget(frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, method=utils.RESIZE_PAD, image_dir="images", parent=self._parent) self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.do_shuffle) control_panel_box.pack_start(self.thumb, expand=False) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # The game control buttons btn_box = gtk.Table(3, 4, False) btn_box.set_row_spacings(2) btn_box.attach(gtk.Label(), 0, 1, 0, 4) btn_box.attach(gtk.Label(), 2, 3, 0, 4) self.btn_solve = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1, 2, 0, 1, 0, 0) self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1, 2, 1, 2, 0, 0) self.btn_add = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1, 2, 2, 3, 0, 0) self.btn_hint = prepare_btn(gtk.ToggleButton(" "), 200) self.labels_to_translate.append([self.btn_hint, _("Board Hint")]) self.btn_hint.connect("clicked", self.do_show_hint) btn_box.attach(self.btn_hint, 1, 2, 3, 4, 0, 0) control_panel_box.pack_start(btn_box, False) self.control_panel_box = control_panel_box # Control panel end panel.pack_start(control_panel, expand=True, fill=True) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game) self.notebook = gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box) inner_table.attach(self.notebook, 1, 2, 0, 1) lang_combo = prepare_btn( LanguageComboBox('org.worldwideworkshop.olpc.JigsawPuzzle')) lang_combo.connect('changed', self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = gtk.HBox(False) vbox = gtk.VBox(False) vbox.pack_start(lang_combo, padding=8) hbox.pack_start(vbox, padding=8) lang_box.add(hbox) inner_table.attach(lang_box, 0, 1, 1, 2, gtk.FILL, gtk.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, padding=8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel(BUDDYMODE_COLLABORATION) self.buddy_panel.show() if not parent._shared_activity: self.do_select_category(self) self.set_contest_mode(False) # Assert consistent state self.cutter_change_cb(None, self.game.get_cutter(), self.game.get_target_pieces_per_line())
class JigsawPuzzleUI(BorderFrame): __gsignals__ = {"game-state-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (int,))} def __init__(self, parent): super(JigsawPuzzleUI, self).__init__(border_color=COLOR_FRAME_OUTER) self._shuffling = False self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE self._readonly = False self._join_time = 0 inner_table = gtk.Table(2, 2, False) self.add(inner_table) self.game = JigsawPuzzleWidget() self.game.connect("picked", self.piece_pick_cb, False) self.game.connect("dropped", self.piece_drop_cb) self.game.connect("solved", self.do_solve) self.game.connect("cutter-changed", self.cutter_change_cb) self.game.show() # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = gtk.VBox() # Logo image img_logo = gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, expand=False, fill=False) # Control panel has the image controls control_panel = BorderFrame( border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS ) control_panel_box = gtk.VBox() scrolled = gtk.ScrolledWindow() scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC scrolled.show() scrolled.add_with_viewport(control_panel_box) scrolled.child.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(COLOR_BG_CONTROLS)) control_panel.add(scrolled) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) btn_box = gtk.Table(2, 5, False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) btn_box.attach(gtk.Label(), 0, 1, 0, 2) # Cut type buttons self.btn_basic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "cut_basic.svg"))) self.btn_basic_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_basic_cut), 1, 2, 0, 1, 0, 0) self.btn_simple_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "cut_simple.svg"))) self.btn_simple_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_simple_cut), 2, 3, 0, 1, 0, 0) self.btn_classic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "cut_classic.svg"))) self.btn_classic_cut.set_image(i) # Link cutter buttons with cutter styles self.btn_cut_mapping = { "basic": self.btn_basic_cut, "simple": self.btn_simple_cut, "classic": self.btn_classic_cut, } for k, v in self.btn_cut_mapping.items(): v.connect("released", self.set_piece_cut, k) btn_box.attach(prepare_btn(self.btn_classic_cut), 3, 4, 0, 1, 0, 0) # Difficulty level buttons self.btn_easy_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "level_easy.svg"))) self.btn_easy_level.set_active(True) self.btn_easy_level.set_image(i) btn_box.attach(prepare_btn(self.btn_easy_level), 1, 2, 1, 2, 0, 0) self.btn_normal_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "level_normal.svg"))) self.btn_normal_level.set_image(i) btn_box.attach(prepare_btn(self.btn_normal_level), 2, 3, 1, 2, 0, 0) self.btn_hard_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "level_hard.svg"))) self.btn_hard_level.set_image(i) # Link level buttons with levels self.btn_level_mapping = {3: self.btn_easy_level, 5: self.btn_normal_level, 8: self.btn_hard_level} for k, v in self.btn_level_mapping.items(): v.connect("released", self.set_level, k) btn_box.attach(prepare_btn(self.btn_hard_level), 3, 4, 1, 2, 0, 0) btn_box.attach(gtk.Label(), 4, 5, 0, 2) control_panel_box.pack_start(btn_box, expand=False) self.thumb = ImageSelectorWidget( frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, method=utils.RESIZE_PAD, image_dir="images", parent=self._parent, ) self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.do_shuffle) control_panel_box.pack_start(self.thumb, expand=False) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # The game control buttons btn_box = gtk.Table(3, 4, False) btn_box.set_row_spacings(2) btn_box.attach(gtk.Label(), 0, 1, 0, 4) btn_box.attach(gtk.Label(), 2, 3, 0, 4) self.btn_solve = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1, 2, 0, 1, 0, 0) self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1, 2, 1, 2, 0, 0) self.btn_add = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1, 2, 2, 3, 0, 0) self.btn_hint = prepare_btn(gtk.ToggleButton(" "), 200) self.labels_to_translate.append([self.btn_hint, _("Board Hint")]) self.btn_hint.connect("clicked", self.do_show_hint) btn_box.attach(self.btn_hint, 1, 2, 3, 4, 0, 0) control_panel_box.pack_start(btn_box, False) self.control_panel_box = control_panel_box # Control panel end panel.pack_start(control_panel, expand=True, fill=True) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game) self.notebook = gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box) inner_table.attach(self.notebook, 1, 2, 0, 1) lang_combo = prepare_btn(LanguageComboBox("org.worldwideworkshop.olpc.JigsawPuzzle")) lang_combo.connect("changed", self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = gtk.HBox(False) vbox = gtk.VBox(False) vbox.pack_start(lang_combo, padding=8) hbox.pack_start(vbox, padding=8) lang_box.add(hbox) inner_table.attach(lang_box, 0, 1, 1, 2, gtk.FILL, gtk.FILL) timer_box = BorderFrame( border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS ) timer_hbox = gtk.HBox(False) self.timer = TimerWidget( bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1] ) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, padding=8) self.timer.connect("timer_toggle", self.timer_toggle_cb) self.msg_label = gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True) self.btn_lesson = prepare_btn(gtk.Button(" ")) self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")]) self.btn_lesson.connect("clicked", self.do_lesson_plan) timer_hbox.pack_start(self.btn_lesson, False, padding=8) vbox = gtk.VBox(False) vbox.pack_start(timer_hbox, padding=8) timer_box.add(vbox) inner_table.attach(timer_box, 1, 2, 1, 2, gtk.FILL, gtk.FILL) # panel.pack_start(lang_box, expand=False, fill=False) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel(BUDDYMODE_COLLABORATION) self.buddy_panel.show() if not parent._shared_activity: self.do_select_category(self) self.set_contest_mode(False) # Assert consistent state self.cutter_change_cb(None, self.game.get_cutter(), self.game.get_target_pieces_per_line()) def set_message(self, msg, frommesh=False): if frommesh and self.get_game_state() != GAME_STARTED: return self.msg_label.set_label(msg) def _set_control_area(self, *args): """ The controls area below the logo needs different actions when in contest mode, and also if we are the contest initiators or not. """ if self._contest_mode: if self.get_game_state() > GAME_IDLE or not self.is_initiator(): self.set_readonly() if self.get_game_state() <= GAME_IDLE: if self.is_initiator(): if self.timer.is_reset(): self.set_message(_("Select image and press Start Game...")) else: self.set_game_state(GAME_STARTED) else: self.set_message(_("Waiting for Puzzle image to be chosen...")) self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) def set_readonly(self): """ In collaborative mode, after an image is selected and the game started you can not change much """ self.thumb.set_readonly(True) self.set_button_translation(self.btn_shuffle, "Game Running") self.btn_shuffle.get_child().set_label(_("Game Running")) self.btn_shuffle.set_sensitive(False) for b in self.btn_cut_mapping.values() + self.btn_level_mapping.values(): if not (b.get_active() and self.is_initiator()): b.set_sensitive(False) self._readonly = True def is_readonly(self): return self._readonly def is_initiator(self): return self._parent.initiating @utils.trace def timer_toggle_cb(self, evt, running): logging.debug("Timer running: %s" % str(running)) if self._contest_mode and running: self.set_game_state(GAME_STARTED) self._send_status_update() def set_contest_mode(self, mode): if getattr(self, "_contest_mode", None) != mode: self.timer.set_can_stop(not bool(mode)) self._contest_mode = bool(mode) self._set_control_area() if self._contest_mode: self.btn_solve.set_sensitive(False) # self.set_button_translation(self.btn_solve, "Give Up") # self.btn_solve.get_child().set_label(_("Give Up")) self.set_button_translation(self.btn_shuffle, "Start Game") self.btn_shuffle.get_child().set_label(_("Start Game")) @utils.trace def set_game_state(self, state, force=False): if state[0] > self._state[0] or force: self._state = state self.emit("game-state-changed", state[0]) self._set_control_area() if state == GAME_STARTED: self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) if self._contest_mode: if self.is_initiator(): self._send_game_update() self._send_status_update() elif state[0] <= GAME_STARTED[0] and self._contest_mode and not self.is_initiator(): c = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(c) def get_game_state(self): return self._state def do_select_category(self, o, *args): if isinstance(o, CategorySelector): self.thumb.set_image_dir(args[0]) # if not self.thumb.category.has_images(): # self.do_add_image(None) else: if self.game.get_parent(): s = CategorySelector(_("Choose a Subject"), self.thumb.get_image_dir(), path="images") s.connect("selected", self.do_select_category) s.show() self.game_box.push(s) s.grab_focus() else: self.game_box.pop() @utils.trace def _show_game(self, pixbuf=None, reshuffle=True): if not self.game.get_parent(): self.game_box.pop() while gtk.events_pending(): gtk.main_iteration(False) c = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(c) if not self.game.prepare_image(pixbuf, reshuffle): self._shuffling = False return self._shuffling = False self.window.set_cursor(None) # self.game.randomize() def do_shuffle(self, o, *args): # if self.thumb.has_image(): # print ("FN", self.thumb.category.filename) if ( self._contest_mode and self.get_game_state() == GAME_IDLE and self.game.is_running() and o == self.btn_shuffle and self.timer.is_reset() ): # Start logging.debug("do_shuffle") self.timer.start() elif self.thumb.has_image(): if not self._shuffling: logging.debug("do_shuffle start") self.timer.stop() self._shuffling = True self._show_game(self.thumb.get_image()) self.timer.reset(False) self.do_show_hint(self.btn_hint) def do_solve(self, o, *args): if not self.game.is_running(): return if not self.game.get_parent(): self.game_box.pop() self.game.solve() self.timer.stop(True) if self._contest_mode: self.set_game_state(GAME_FINISHED) self.set_message(_("Puzzle Solved!")) self.control_panel_box.foreach(self.control_panel_box.remove) lbl = gtk.Label(_("Press Stop on the Toolbar to Exit Activity!")) lbl.modify_font(pango.FontDescription("bold 9")) lbl.set_line_wrap(True) lbl.set_justify(gtk.JUSTIFY_CENTER) lbl.set_size_request(200, -1) lbl.show() self.control_panel_box.pack_start(lbl, True) def do_add_image(self, o, *args): if self._contest_mode and self.get_game_state() >= GAME_STARTED: # Buddy Panel if not self.buddy_panel.get_parent(): # self.timer.stop() self.game_box.push(self.buddy_panel) else: self.game_box.pop() else: self.thumb.add_image() @utils.trace def do_select_language(self, combo, *args): self.selected_lang_details = combo.translations[combo.get_active()] self.refresh_labels() def do_show_hint(self, o, *args): self.game.show_hint(o.get_active()) def set_button_translation(self, btn, translation): for i in range(len(self.labels_to_translate)): if self.labels_to_translate[i][0] == btn: self.labels_to_translate[i][1] = translation break def refresh_labels(self, first_time=False): self._parent.set_title(_("Jigsaw Puzzle Activity")) for lbl in self.labels_to_translate: if isinstance(lbl[0], gtk.Button): lbl[0].get_child().set_label(_(lbl[1])) else: lbl[0].set_label(_(lbl[1])) if not self.game.get_parent() and not first_time: self.game_box.pop() if self.notebook.get_current_page() == 1: m = self.do_lesson_plan else: m = self.do_select_category m(self) def do_lesson_plan(self, btn): page = self.notebook.get_current_page() if page == 0: if self.notebook.get_n_pages() == 1: lessons = NotebookReaderWidget("lessons", self.selected_lang_details) lessons.connect("parent-set", self.do_lesson_plan_reparent) lessons.show_all() self.notebook.append_page(lessons) self.notebook.set_current_page(int(not page)) def do_lesson_plan_reparent(self, widget, oldparent): if not self.btn_lesson.get_child(): return if widget.parent is None: self.set_button_translation(self.btn_lesson, "Lesson Plans") self.btn_lesson.get_child().set_label(_("Lesson Plans")) else: self.set_button_translation(self.btn_lesson, "Close Lesson") self.btn_lesson.get_child().set_label(_("Close Lesson")) def set_piece_cut(self, btn, cutter, *args): if self.is_readonly(): return self.game.set_cutter(cutter) if self.game.is_running(): self.do_shuffle(btn) def cutter_change_cb(self, o, cutter, tppl): # tppl = target pieces per line for c, b in self.btn_cut_mapping.items(): if c == cutter: b.set_sensitive(True) b.set_active(True) else: b.set_active(False) for c, b in self.btn_level_mapping.items(): if c == tppl: b.set_sensitive(True) b.set_active(True) else: b.set_active(False) def set_level(self, btn, level, *args): if self.is_readonly(): return self.game.set_target_pieces_per_line(level) if self.game.is_running(): self.do_shuffle(btn) def piece_pick_cb(self, o, piece, from_mesh=False): if not self.timer.is_running(): self.timer.start() if not from_mesh: self._send_pick_notification(piece) def piece_drop_cb(self, o, piece, from_mesh=False): if self._parent._shared_activity and not from_mesh: self._send_drop_notification(piece) def _freeze(self, journal=True): if journal: return {"thumb": self.thumb._freeze(), "timer": self.timer._freeze(), "game": self.game._freeze()} else: return {"timer": self.timer._freeze(), "game": self.game._freeze(img_cksum_only=True)} def _thaw(self, data): self.timer.reset() for k in ("thumb", "timer", "game"): if data.has_key(k): logging.debug("_thaw data for %s: %s" % (k, data)) getattr(self, k)._thaw(data[k]) if data.has_key("game"): # and not data.has_key('thumb'): self.thumb.load_pb(self.game.board.cutboard.pb) if data.has_key("timer"): self._join_time = self.timer.ellapsed() if data.has_key("game") and data["game"]["piece_pos"]: self._show_game(reshuffle=False) @utils.trace def _send_status_update(self): """ Send a status update signal """ if self._parent._shared_activity: if self.get_game_state() == GAME_STARTED: if self.thumb.has_image(): self.set_message(_("Game Started!")) else: self.set_message(_("Waiting for Puzzle image to be transferred...")) self._parent.game_tube.StatusUpdate(self._state[1], self._join_time) @utils.trace def _send_game_update(self): """ A puzzle was selected, share it """ if self._parent._shared_activity: # TODO: Send image self._parent.game_tube.GameUpdate(self._state[1]) @utils.trace def _send_pick_notification(self, piece): """ """ if self._parent._shared_activity: self._parent.game_tube.PiecePicked(piece.get_index()) @utils.trace def _recv_pick_notification(self, index): for piece in self.game.get_floating_pieces(): if piece.get_index() == index: logging.debug("Remote picked piece %s" % piece) piece.set_sensitive(False) @utils.trace def _send_drop_notification(self, piece): """ """ if piece.placed: self._parent.game_tube.PiecePlaced(piece.get_index()) else: self._parent.game_tube.PieceDropped(piece.get_index(), piece.get_position()) @utils.trace def _recv_drop_notification(self, index, position=None): for piece in self.game.get_floating_pieces(): if piece.get_index() == index: logging.debug("Moving piece %s" % piece) if position is None: self.game.board.place_piece(piece) else: self.game._move_cb(piece, position[0], position[1], absolute=True) self.game._drop_cb(piece, from_mesh=True) piece.set_sensitive(True) break
def __init__(self, parent): super(JigsawPuzzleUI, self).__init__(border_color=COLOR_FRAME_OUTER) self._shuffling = False self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE self._readonly = False self._join_time = 0 inner_table = gtk.Table(2, 2, False) self.add(inner_table) self.game = JigsawPuzzleWidget() self.game.connect("picked", self.piece_pick_cb, False) self.game.connect("dropped", self.piece_drop_cb) self.game.connect("solved", self.do_solve) self.game.connect("cutter-changed", self.cutter_change_cb) self.game.show() # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = gtk.VBox() # Logo image img_logo = gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, expand=False, fill=False) # Control panel has the image controls control_panel = BorderFrame( border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS ) control_panel_box = gtk.VBox() scrolled = gtk.ScrolledWindow() scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC scrolled.show() scrolled.add_with_viewport(control_panel_box) scrolled.child.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(COLOR_BG_CONTROLS)) control_panel.add(scrolled) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) btn_box = gtk.Table(2, 5, False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) btn_box.attach(gtk.Label(), 0, 1, 0, 2) # Cut type buttons self.btn_basic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "cut_basic.svg"))) self.btn_basic_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_basic_cut), 1, 2, 0, 1, 0, 0) self.btn_simple_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "cut_simple.svg"))) self.btn_simple_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_simple_cut), 2, 3, 0, 1, 0, 0) self.btn_classic_cut = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "cut_classic.svg"))) self.btn_classic_cut.set_image(i) # Link cutter buttons with cutter styles self.btn_cut_mapping = { "basic": self.btn_basic_cut, "simple": self.btn_simple_cut, "classic": self.btn_classic_cut, } for k, v in self.btn_cut_mapping.items(): v.connect("released", self.set_piece_cut, k) btn_box.attach(prepare_btn(self.btn_classic_cut), 3, 4, 0, 1, 0, 0) # Difficulty level buttons self.btn_easy_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "level_easy.svg"))) self.btn_easy_level.set_active(True) self.btn_easy_level.set_image(i) btn_box.attach(prepare_btn(self.btn_easy_level), 1, 2, 1, 2, 0, 0) self.btn_normal_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "level_normal.svg"))) self.btn_normal_level.set_image(i) btn_box.attach(prepare_btn(self.btn_normal_level), 2, 3, 1, 2, 0, 0) self.btn_hard_level = gtk.ToggleButton() i = gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join("icons", "level_hard.svg"))) self.btn_hard_level.set_image(i) # Link level buttons with levels self.btn_level_mapping = {3: self.btn_easy_level, 5: self.btn_normal_level, 8: self.btn_hard_level} for k, v in self.btn_level_mapping.items(): v.connect("released", self.set_level, k) btn_box.attach(prepare_btn(self.btn_hard_level), 3, 4, 1, 2, 0, 0) btn_box.attach(gtk.Label(), 4, 5, 0, 2) control_panel_box.pack_start(btn_box, expand=False) self.thumb = ImageSelectorWidget( frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, method=utils.RESIZE_PAD, image_dir="images", parent=self._parent, ) self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.do_shuffle) control_panel_box.pack_start(self.thumb, expand=False) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # The game control buttons btn_box = gtk.Table(3, 4, False) btn_box.set_row_spacings(2) btn_box.attach(gtk.Label(), 0, 1, 0, 4) btn_box.attach(gtk.Label(), 2, 3, 0, 4) self.btn_solve = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1, 2, 0, 1, 0, 0) self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1, 2, 1, 2, 0, 0) self.btn_add = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1, 2, 2, 3, 0, 0) self.btn_hint = prepare_btn(gtk.ToggleButton(" "), 200) self.labels_to_translate.append([self.btn_hint, _("Board Hint")]) self.btn_hint.connect("clicked", self.do_show_hint) btn_box.attach(self.btn_hint, 1, 2, 3, 4, 0, 0) control_panel_box.pack_start(btn_box, False) self.control_panel_box = control_panel_box # Control panel end panel.pack_start(control_panel, expand=True, fill=True) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game) self.notebook = gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box) inner_table.attach(self.notebook, 1, 2, 0, 1) lang_combo = prepare_btn(LanguageComboBox("org.worldwideworkshop.olpc.JigsawPuzzle")) lang_combo.connect("changed", self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = gtk.HBox(False) vbox = gtk.VBox(False) vbox.pack_start(lang_combo, padding=8) hbox.pack_start(vbox, padding=8) lang_box.add(hbox) inner_table.attach(lang_box, 0, 1, 1, 2, gtk.FILL, gtk.FILL) timer_box = BorderFrame( border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS ) timer_hbox = gtk.HBox(False) self.timer = TimerWidget( bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1] ) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, padding=8) self.timer.connect("timer_toggle", self.timer_toggle_cb) self.msg_label = gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True) self.btn_lesson = prepare_btn(gtk.Button(" ")) self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")]) self.btn_lesson.connect("clicked", self.do_lesson_plan) timer_hbox.pack_start(self.btn_lesson, False, padding=8) vbox = gtk.VBox(False) vbox.pack_start(timer_hbox, padding=8) timer_box.add(vbox) inner_table.attach(timer_box, 1, 2, 1, 2, gtk.FILL, gtk.FILL) # panel.pack_start(lang_box, expand=False, fill=False) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel(BUDDYMODE_COLLABORATION) self.buddy_panel.show() if not parent._shared_activity: self.do_select_category(self) self.set_contest_mode(False) # Assert consistent state self.cutter_change_cb(None, self.game.get_cutter(), self.game.get_target_pieces_per_line())
def __init__(self, parent): super(SliderPuzzleUI, self).__init__(3, 3, False) self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE inner_table = Gtk.Table(2, 2, False) self.add(inner_table) self.from_journal = True self.game = SliderPuzzleWidget(9, GAME_SIZE, GAME_SIZE) self.game.connect("solved", self.do_solve) self.game.connect("moved", self.slider_move_cb) self._parent.connect("key_press_event", self.game.process_key) self._parent.connect("key_press_event", self.process_key) self.game.show() desktop = BorderFrame(border_color=COLOR_FRAME_CONTROLS) desktop.show() desktop.add(self.game) self.game_wrapper = Gtk.VBox() self.game_wrapper.show() inner = Gtk.HBox() inner.show() #BorderFrame(border=BORDER_ALL_BUT_BOTTOM, # border_color=COLOR_FRAME_CONTROLS, # bg_color=COLOR_BG_CONTROLS) inner.pack_start(desktop, True, False, 0) self.game_wrapper.pack_start(inner, True, False, 0) # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = Gtk.VBox() # Logo image img_logo = Gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, False, False, 0) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = Gtk.VBox() control_panel.add(control_panel_box) spacer = Gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, False, False, 0) # ... # Slice buttons #btn_box = Gtk.Table(1,5,False) #btn_box.set_col_spacings(5) #btn_box.set_row_spacings(5) #btn_box.attach(Gtk.Label(), 0,1,0,2) #spacer = Gtk.Label() #spacer.set_size_request(-1, 15) #control_panel_box.pack_start(spacer, False, False, 0) #cutter = Gtk.HBox(False, 8) #cutter.pack_start(Gtk.Label(), True) #self.btn_9 = prepare_btn(Gtk.ToggleButton("9"),SLICE_BTN_WIDTH) #self.btn_9.set_active(True) #self.btn_9.connect("clicked", self.set_nr_pieces, 9) #btn_box.attach(self.btn_9, 1,2,0,1,0,0) #cutter.pack_start(self.btn_9, False, False) #self.btn_12 = prepare_btn(Gtk.ToggleButton("12"), SLICE_BTN_WIDTH) #self.btn_12.connect("clicked", self.set_nr_pieces, 12) #btn_box.attach(self.btn_12, 2,3,0,1,0,0) #cutter.pack_start(self.btn_12, False, False) #self.btn_16 = prepare_btn(Gtk.ToggleButton("16"), SLICE_BTN_WIDTH) #self.btn_16.connect("clicked", self.set_nr_pieces, 16) #btn_box.attach(self.btn_16, 3,4,0,1,0,0) #cutter.pack_start(self.btn_16, False, False) #cutter.pack_start(Gtk.Label(), True) #control_panel_box.pack_start(cutter, True) #spacer = Gtk.Label() #spacer.set_size_request(-1, 10) #control_panel_box.pack_start(spacer, False) #btn_box.attach(Gtk.Label(), 4,5,0,1) #control_panel_box.pack_start(btn_box, False, True, 0) self.thumb = ImageSelectorWidget(self._parent, frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, image_dir='images') #self.thumb.connect("category_press", self.do_select_category) #self.thumb.connect("image_press", self.set_nr_pieces) #control_panel_box.pack_start(self.thumb, False, True, 0) spacer = Gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, False, False, 0) # The game control buttons #btn_box = Gtk.Table(3,3,False) #btn_box.set_row_spacings(2) #btn_box.attach(Gtk.Label(), 0,1,0,3) #btn_box.attach(Gtk.Label(), 2,3,0,3) #self.btn_solve = prepare_btn(Gtk.Button(" "), 200) #self.labels_to_translate.append([self.btn_solve, _("Solve")]) #self.btn_solve.connect("clicked", self.do_solve) #btn_box.attach(self.btn_solve, 1,2,0,1,0,0) #self.btn_shuffle = prepare_btn(Gtk.Button(" "), 200) #self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) #self.btn_shuffle.connect("clicked", self.do_shuffle) #btn_box.attach(self.btn_shuffle, 1,2,1,2,0,0) #self.btn_add = prepare_btn(Gtk.Button(" "), 200) #self.labels_to_translate.append([self.btn_add, _("My Picture")]) #self.btn_add.connect("clicked", self.do_add_image) #btn_box.attach(self.btn_add, 1,2,2,3,0,0) #control_panel_box.pack_start(btn_box, False, True, 0) # Control panel end panel.pack_start(control_panel, True, True, 0) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game_wrapper) lang_combo = prepare_btn( LanguageComboBox('org.worldwideworkshop.olpc.SliderPuzzle')) lang_combo.connect('changed', self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = Gtk.HBox(False) vbox = Gtk.VBox(False) vbox.pack_start(lang_combo, True, True, 8) hbox.pack_start(vbox, True, True, 8) lang_box.add(hbox) inner_table.attach(lang_box, 0, 1, 1, 2, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = Gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, True, 8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = Gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True, True, 0) self.notebook = Gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box, None) inner_table.attach(self.notebook, 1, 2, 0, 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL) self.btn_lesson = prepare_btn(Gtk.Button(" ")) self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")]) self.btn_lesson.connect("clicked", self.do_lesson_plan) timer_hbox.pack_start(self.btn_lesson, False, True, 8) vbox = Gtk.VBox(False) vbox.pack_start(timer_hbox, True, True, 8) timer_box.add(vbox) inner_table.attach(timer_box, 1, 2, 1, 2, Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, Gtk.AttachOptions.FILL) panel.pack_start(lang_box, False, False, 0) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel() self.buddy_panel.show() if not parent.shared_activity: self.do_select_category(self) else: self.set_message(_("Waiting for remote game...")) # Contest mode flags self.set_contest_mode(False) self._on_lesson_plan = False
class SliderPuzzleUI(Gtk.Table): __gsignals__ = { 'game-state-changed': (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (int, )) } def __init__(self, parent): super(SliderPuzzleUI, self).__init__(3, 3, False) self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE inner_table = Gtk.Table(2, 2, False) self.add(inner_table) self.from_journal = True self.game = SliderPuzzleWidget(9, GAME_SIZE, GAME_SIZE) self.game.connect("solved", self.do_solve) self.game.connect("moved", self.slider_move_cb) self._parent.connect("key_press_event", self.game.process_key) self._parent.connect("key_press_event", self.process_key) self.game.show() desktop = BorderFrame(border_color=COLOR_FRAME_CONTROLS) desktop.show() desktop.add(self.game) self.game_wrapper = Gtk.VBox() self.game_wrapper.show() inner = Gtk.HBox() inner.show() #BorderFrame(border=BORDER_ALL_BUT_BOTTOM, # border_color=COLOR_FRAME_CONTROLS, # bg_color=COLOR_BG_CONTROLS) inner.pack_start(desktop, True, False, 0) self.game_wrapper.pack_start(inner, True, False, 0) # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = Gtk.VBox() # Logo image img_logo = Gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, False, False, 0) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = Gtk.VBox() control_panel.add(control_panel_box) spacer = Gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, False, False, 0) # ... # Slice buttons #btn_box = Gtk.Table(1,5,False) #btn_box.set_col_spacings(5) #btn_box.set_row_spacings(5) #btn_box.attach(Gtk.Label(), 0,1,0,2) #spacer = Gtk.Label() #spacer.set_size_request(-1, 15) #control_panel_box.pack_start(spacer, False, False, 0) #cutter = Gtk.HBox(False, 8) #cutter.pack_start(Gtk.Label(), True) #self.btn_9 = prepare_btn(Gtk.ToggleButton("9"),SLICE_BTN_WIDTH) #self.btn_9.set_active(True) #self.btn_9.connect("clicked", self.set_nr_pieces, 9) #btn_box.attach(self.btn_9, 1,2,0,1,0,0) #cutter.pack_start(self.btn_9, False, False) #self.btn_12 = prepare_btn(Gtk.ToggleButton("12"), SLICE_BTN_WIDTH) #self.btn_12.connect("clicked", self.set_nr_pieces, 12) #btn_box.attach(self.btn_12, 2,3,0,1,0,0) #cutter.pack_start(self.btn_12, False, False) #self.btn_16 = prepare_btn(Gtk.ToggleButton("16"), SLICE_BTN_WIDTH) #self.btn_16.connect("clicked", self.set_nr_pieces, 16) #btn_box.attach(self.btn_16, 3,4,0,1,0,0) #cutter.pack_start(self.btn_16, False, False) #cutter.pack_start(Gtk.Label(), True) #control_panel_box.pack_start(cutter, True) #spacer = Gtk.Label() #spacer.set_size_request(-1, 10) #control_panel_box.pack_start(spacer, False) #btn_box.attach(Gtk.Label(), 4,5,0,1) #control_panel_box.pack_start(btn_box, False, True, 0) self.thumb = ImageSelectorWidget(self._parent, frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, image_dir='images') #self.thumb.connect("category_press", self.do_select_category) #self.thumb.connect("image_press", self.set_nr_pieces) #control_panel_box.pack_start(self.thumb, False, True, 0) spacer = Gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, False, False, 0) # The game control buttons #btn_box = Gtk.Table(3,3,False) #btn_box.set_row_spacings(2) #btn_box.attach(Gtk.Label(), 0,1,0,3) #btn_box.attach(Gtk.Label(), 2,3,0,3) #self.btn_solve = prepare_btn(Gtk.Button(" "), 200) #self.labels_to_translate.append([self.btn_solve, _("Solve")]) #self.btn_solve.connect("clicked", self.do_solve) #btn_box.attach(self.btn_solve, 1,2,0,1,0,0) #self.btn_shuffle = prepare_btn(Gtk.Button(" "), 200) #self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) #self.btn_shuffle.connect("clicked", self.do_shuffle) #btn_box.attach(self.btn_shuffle, 1,2,1,2,0,0) #self.btn_add = prepare_btn(Gtk.Button(" "), 200) #self.labels_to_translate.append([self.btn_add, _("My Picture")]) #self.btn_add.connect("clicked", self.do_add_image) #btn_box.attach(self.btn_add, 1,2,2,3,0,0) #control_panel_box.pack_start(btn_box, False, True, 0) # Control panel end panel.pack_start(control_panel, True, True, 0) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game_wrapper) lang_combo = prepare_btn( LanguageComboBox('org.worldwideworkshop.olpc.SliderPuzzle')) lang_combo.connect('changed', self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = Gtk.HBox(False) vbox = Gtk.VBox(False) vbox.pack_start(lang_combo, True, True, 8) hbox.pack_start(vbox, True, True, 8) lang_box.add(hbox) inner_table.attach(lang_box, 0, 1, 1, 2, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = Gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, True, 8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = Gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True, True, 0) self.notebook = Gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box, None) inner_table.attach(self.notebook, 1, 2, 0, 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL) self.btn_lesson = prepare_btn(Gtk.Button(" ")) self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")]) self.btn_lesson.connect("clicked", self.do_lesson_plan) timer_hbox.pack_start(self.btn_lesson, False, True, 8) vbox = Gtk.VBox(False) vbox.pack_start(timer_hbox, True, True, 8) timer_box.add(vbox) inner_table.attach(timer_box, 1, 2, 1, 2, Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, Gtk.AttachOptions.FILL) panel.pack_start(lang_box, False, False, 0) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel() self.buddy_panel.show() if not parent.shared_activity: self.do_select_category(self) else: self.set_message(_("Waiting for remote game...")) # Contest mode flags self.set_contest_mode(False) self._on_lesson_plan = False def set_message(self, msg, frommesh=False): if frommesh and self.get_game_state() < GAME_STARTED: return self.msg_label.set_label(msg) def is_initiator(self): return self._parent.initiating def set_readonly(self, ro=True): self.thumb.set_readonly(ro) #for b in (self.btn_9, self.btn_12, self.btn_16): # if not b.get_active(): # b.set_sensitive(False) @utils.trace def timer_toggle_cb(self, evt, running): logging.debug("Timer running: %s" % str(running)) if self._contest_mode and running: self.set_game_state(GAME_STARTED) self._send_status_update() #if self._contest_mode: # if running: # if self.game.filename and not self.game_wrapper.get_parent(): # self.game_box.pop() # else: # if not self.buddy_panel.get_parent(): # self.game_box.push(self.buddy_panel) def _set_control_area(self, *args): """ The controls area below the logo needs different actions when in contest mode, and also if we are the contest initiators or not. """ if self._contest_mode: if self.get_game_state() > GAME_IDLE: self.set_readonly() else: if self.is_initiator(): if self.timer.is_reset(): self.set_message( _("Select image and press Start Game...")) else: self.set_game_state(GAME_STARTED) else: self.set_message( _("Waiting for Puzzle image to be chosen...")) self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) def set_game_state(self, state, force=False): if state[0] > self._state[0] or force: self._state = state self.emit('game-state-changed', state[0]) self._set_control_area() if state == GAME_STARTED: self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) self._send_status_update() def get_game_state(self): return self._state def set_button_translation(self, btn, translation): for i in range(len(self.labels_to_translate)): if self.labels_to_translate[i][0] == btn: self.labels_to_translate[i][1] = translation break def set_contest_mode(self, mode): if getattr(self, '_contest_mode', None) != mode: self._contest_mode = bool(mode) self._set_control_area() if self._contest_mode: self.set_button_translation(self.btn_solve, "Give Up") self.btn_solve.get_child().set_label(_("Give Up")) self.set_button_translation(self.btn_shuffle, "Start Game") self.btn_shuffle.get_child().set_label(_("Start Game")) def is_contest_mode(self): return self._contest_mode # and self.game.filename def do_select_language(self, combo, *args): self.selected_lang_details = combo.translations[combo.get_active()] self.refresh_labels() def refresh_labels(self, first_time=False): self._parent.set_title(_("Slider Puzzle Activity")) for lbl in self.labels_to_translate: if isinstance(lbl[0], Gtk.Button): lbl[0].get_child().set_label(_(lbl[1])) else: lbl[0].set_label(_(lbl[1])) if not self.game_wrapper.get_parent() and not first_time: self.game_box.pop() if self.notebook.get_current_page() == 1: m = self.do_lesson_plan else: m = self.do_select_category m(self) @utils.trace def set_nr_pieces(self, btn=None, nr_pieces=None, path=None, path_from_journal=None): #if isinstance(btn, gtk.ToggleButton) and not btn.get_active(): # return logger.debug('final path') if self.is_contest_mode() and nr_pieces == self.game.get_nr_pieces(): return #if isinstance(btn, gtk.ToggleButton): #if not btn.get_active(): # if nr_pieces == self.game.get_nr_pieces(): # logging.debug("A") # btn.set_active(True) # return if nr_pieces is None: nr_pieces = self.game.get_nr_pieces() if btn is None: #not isinstance(btn, gtk.ToggleButton): if self._contest_mode: self.set_game_state(GAME_STARTED) #for n, b in ((9, self.btn_9),(12, self.btn_12),(16, self.btn_16)): # if n == nr_pieces and not b.get_active(): # logging.debug("B") # b.set_sensitive(True) # b.set_active(True) return #if self.thumb.has_image(): logger.debug('nr ends1') if not self.game_wrapper.get_parent(): self.game_box.pop() logger.debug('nr ends2') logger.debug('nr ends3') if not path: self.yy = self.pre_path logger.debug('nr ends0') else: self.yy = path if self.from_journal: self.yy = path_from_journal self.px = utils.load_image(self.yy) logger.debug('nr ends5') self.game.load_image(self.px) logger.debug('nr ends6') #self.thumb.set_game_widget(self.game) logger.debug('nr ends4') self.game.set_nr_pieces(nr_pieces) self.timer.reset(False) #if isinstance(btn, gtk.ToggleButton): #for n, b in ((9, self.btn_9),(12, self.btn_12),(16, self.btn_16)): # if b is not btn: # logging.debug("C") # b.set_active(False) # b.set_sensitive(not self._contest_mode) def _set_nr_pieces_pre(self, img_path): logger.debug('pre path') self.from_journal = False self.pre_path = img_path self.set_nr_pieces(nr_pieces=9, path=img_path) def do_shuffle(self, *args, **kwargs): if self._contest_mode: if self.get_game_state() > GAME_IDLE: # Restart self.set_game_state(GAME_STARTED, True) self._parent.frozen.thaw() self.timer.reset(True) elif self.game.filename is not None and self.timer.is_reset(): # Start self.timer.start() #elif self.thumb.has_image(): if not self.game_wrapper.get_parent(): self.game_box.pop() self.game.load_image(self.px) #self.thumb.set_game_widget(self.game) self.game.randomize() self.timer.reset(False) def slider_move_cb(self, *args): if not self.timer.is_running(): self.timer.start() def do_solve(self, btn): if self.game.filename is not None: if not self.game_wrapper.get_parent(): self.game_box.pop() self.game.show_image() self.timer.stop(True) if self._contest_mode and self.get_game_state() == GAME_STARTED: if btn != self.btn_solve: self.set_game_state(GAME_FINISHED) self.set_message(_("Puzzle Solved!")) else: self.set_game_state(GAME_QUIT) self.set_message(_("Gave Up")) self._set_control_area() # @utils.trace # def do_select_category(self, owner, *args, **kwargs): # if isinstance(owner, CategorySelector): # self.thumb.set_image_dir(args[0]) # #self.game_box.pop() # if not self.thumb.category.has_images(): # self.do_add_image(None) # else: # if self.game_wrapper.get_parent(): # s = CategorySelector("images", _("Choose a Subject"), self.thumb.get_image_dir()) # s.connect("selected", self.do_select_category) # s.show() # self.game_box.push(s) # s.grab_focus() # else: # self.game_box.pop() def do_select_category(self, o, *args): if isinstance(o, CategorySelector): self.thumb.set_image_dir(args[0]) #if not self.thumb.category.has_images(): # self.do_add_image(None) else: if self.game_wrapper.get_parent(): logging.debug("Current cat dir=%s" % self.thumb.get_image_dir()) s = CategorySelector(_("Choose a Subject"), self.thumb.get_image_dir(), path="images") #extra=('images/Sequencing Puzzles',)) s.connect("selected", self.do_select_category) s.show() self.game_box.push(s) s.grab_focus() else: self.game_box.pop() @utils.trace def do_add_image(self, widget, *args): """ Use to trigger and process the My Own Image selector. Also used for showing the buddies panel on contest mode""" self.from_journal = True if self._contest_mode and self.get_game_state() >= GAME_STARTED: # Buddy Panel if not self.buddy_panel.get_parent(): self.timer.stop() self.game_box.push(self.buddy_panel) else: self.game_box.pop() elif self._contest_mode and not self.is_initiator(): # do nothing pass else: self.add_image() #self.set_nr_pieces(nr_pieces = 9) self.do_shuffle() #if response is None: # else: # # My Own Image selector # imgfilter = gtk.FileFilter() # imgfilter.set_name(_("Image Files")) # imgfilter.add_mime_type('image/*') # fd = gtk.FileChooserDialog(title=_("Select Image File"), parent=self._parent, # action=gtk.FILE_CHOOSER_ACTION_OPEN, # buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) # # fd.set_current_folder(os.path.expanduser("~/")) # fd.set_modal(True) # fd.add_filter(imgfilter) # fd.connect("response", self.do_add_image) # fd.resize(800,600) # fd.show() #else: # if response == gtk.RESPONSE_ACCEPT: # if self.thumb.load_image(widget.get_filename()): # self.do_shuffle() # else: # err = gtk.MessageDialog(self._parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, # _("Not a valid image file")) # err.run() # err.destroy() # return # widget.destroy() def add_image(self, *args): #widget=None, response=None, *args): """ Use to trigger and process the My Own Image selector. """ if hasattr(mime, 'GENERIC_TYPE_IMAGE'): filter = {'what_filter': mime.GENERIC_TYPE_IMAGE} else: filter = {} chooser = ObjectChooser(self._parent, **filter) try: result = chooser.run() if result == Gtk.ResponseType.ACCEPT: jobject = chooser.get_selected_object() if jobject and jobject.file_path: #if self.load_image(str(jobject.file_path), True): self.set_nr_pieces(nr_pieces=9, path_from_journal=str( jobject.file_path)) pass # else: # err = Gtk.MessageDialog(self._parent, Gtk.DialogFlags.MODAL, Gtk.MESSAGE_ERROR, Gtk.BUTTONS_OK, # _("Not a valid image file")) # err.run() # err.destroy() # return finally: chooser.destroy() del chooser def do_lesson_plan(self, btn): if self._on_lesson_plan: return try: self._on_lesson_plan = True if self._contest_mode and self.get_game_state() < GAME_STARTED: return page = self.notebook.get_current_page() if page == 0: self.timer.stop() self.timer.props.sensitive = False if self.notebook.get_n_pages() == 1: lessons = NotebookReaderWidget('lessons', self.selected_lang_details) lessons.connect('parent-set', self.do_lesson_plan_reparent) lessons.show_all() self.notebook.append_page(lessons, None) else: self.timer.props.sensitive = True self.notebook.set_current_page(int(not page)) finally: self._on_lesson_plan = False def do_lesson_plan_reparent(self, widget, oldparent): if widget.parent is None: self.set_button_translation(self.btn_lesson, "Lesson Plans") self.btn_lesson.get_child().set_label(_("Lesson Plans")) else: self.set_button_translation(self.btn_lesson, "Close Lesson") self.btn_lesson.get_child().set_label(_("Close Lesson")) def process_key(self, w, e): """ The callback for key processing. The button shortcuts are all defined here. """ k = Gdk.keyval_name(e.keyval) if not isinstance(self._parent.get_focus(), Gtk.Editable): if k == '1': self.set_nr_pieces(nr_pieces=9) return True if k == '2': self.set_nr_pieces(nr_pieces=12) return True if k == '3': self.set_nr_pieces(nr_pieces=16) return True if k == 'Return': self.set_nr_pieces(None) return True if k in ('Escape', 'q'): gtk.main_quit() return True return False @utils.trace def _freeze(self, journal=True): """ returns a json writable object representation capable of being used to restore our current status """ return (self.thumb._freeze(), self.game._freeze(journal=journal), self.game.get_nr_pieces(), self.timer._freeze()) def _thaw(self, obj): """ retrieves a frozen status from a python object, as per _freeze """ logging.debug('_thaw: %s' % obj) if not obj[1]['image']: return if not obj[1].has_key('image'): self.game.load_image(self.thumb.get_image()) self.set_nr_pieces(None, obj[2]) logging.debug(obj[1].keys()) wimg = obj[1].has_key('image') self.game._thaw(obj[1]) if wimg: logging.debug("Forcing thumb image from the one in game") self.thumb.load_pb(self.game.image) self.timer.reset() self.timer._thaw(obj[3]) self.game_box.pop() @utils.trace def _send_status_update(self): """ Send a status update signal """ if self._parent.shared_activity: if self.get_game_state() == GAME_STARTED: if self.thumb.has_image(): self.set_message(_("Game Started!")) self._parent.game_tube.StatusUpdate(self._state[1], self.timer.is_running(), self.timer.ellapsed())
def __init__(self, parent): super(SliderPuzzleUI, self).__init__(3,3,False) self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE inner_table = gtk.Table(2,2,False) self.add(inner_table) self.game = SliderPuzzleWidget(9, GAME_SIZE, GAME_SIZE) self.game.connect("solved", self.do_solve) self.game.connect("moved", self.slider_move_cb) self._parent.connect("key_press_event",self.game.process_key) self._parent.connect("key_press_event",self.process_key) self.game.show() desktop = BorderFrame(border_color=COLOR_FRAME_CONTROLS) desktop.show() desktop.add(self.game) self.game_wrapper = gtk.VBox() self.game_wrapper.show() inner = gtk.HBox() inner.show() #BorderFrame(border=BORDER_ALL_BUT_BOTTOM, # border_color=COLOR_FRAME_CONTROLS, # bg_color=COLOR_BG_CONTROLS) inner.pack_start(desktop, expand=True, fill=False) self.game_wrapper.pack_start(inner, expand=True, fill=False) # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = gtk.VBox() # Logo image img_logo = gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, expand=False, fill=False) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = gtk.VBox() control_panel.add(control_panel_box) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # ... # Slice buttons btn_box = gtk.Table(1,5,False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) btn_box.attach(gtk.Label(), 0,1,0,2) #spacer = gtk.Label() #spacer.set_size_request(-1, 15) #control_panel_box.pack_start(spacer, expand=False, fill=False) #cutter = gtk.HBox(False, 8) #cutter.pack_start(gtk.Label(), True) self.btn_9 = prepare_btn(gtk.ToggleButton("9"),SLICE_BTN_WIDTH) self.btn_9.set_active(True) self.btn_9.connect("clicked", self.set_nr_pieces, 9) btn_box.attach(self.btn_9, 1,2,0,1,0,0) #cutter.pack_start(self.btn_9, False, False) self.btn_12 = prepare_btn(gtk.ToggleButton("12"), SLICE_BTN_WIDTH) self.btn_12.connect("clicked", self.set_nr_pieces, 12) btn_box.attach(self.btn_12, 2,3,0,1,0,0) #cutter.pack_start(self.btn_12, False, False) self.btn_16 = prepare_btn(gtk.ToggleButton("16"), SLICE_BTN_WIDTH) self.btn_16.connect("clicked", self.set_nr_pieces, 16) btn_box.attach(self.btn_16, 3,4,0,1,0,0) #cutter.pack_start(self.btn_16, False, False) #cutter.pack_start(gtk.Label(), True) #control_panel_box.pack_start(cutter, True) #spacer = gtk.Label() #spacer.set_size_request(-1, 10) #control_panel_box.pack_start(spacer, False) btn_box.attach(gtk.Label(), 4,5,0,1) control_panel_box.pack_start(btn_box, expand=False) self.thumb = ImageSelectorWidget(self._parent,frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, image_dir='images') self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.set_nr_pieces) control_panel_box.pack_start(self.thumb, False) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # The game control buttons btn_box = gtk.Table(3,3,False) btn_box.set_row_spacings(2) btn_box.attach(gtk.Label(), 0,1,0,3) btn_box.attach(gtk.Label(), 2,3,0,3) self.btn_solve = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1,2,0,1,0,0) self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1,2,1,2,0,0) self.btn_add = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1,2,2,3,0,0) control_panel_box.pack_start(btn_box, False) # Control panel end panel.pack_start(control_panel, expand=True, fill=True) inner_table.attach(panel, 0,1,0,1,0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game_wrapper) lang_combo = prepare_btn(LanguageComboBox('org.worldwideworkshop.olpc.SliderPuzzle')) lang_combo.connect('changed', self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = gtk.HBox(False) vbox = gtk.VBox(False) vbox.pack_start(lang_combo, padding=8) hbox.pack_start(vbox, padding=8) lang_box.add(hbox) inner_table.attach(lang_box, 0,1,1,2,gtk.FILL, gtk.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, padding=8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True) self.notebook = gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box) inner_table.attach(self.notebook, 1,2,0,1, gtk.FILL, gtk.FILL) self.btn_lesson = prepare_btn(gtk.Button(" ")) self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")]) self.btn_lesson.connect("clicked", self.do_lesson_plan) timer_hbox.pack_start(self.btn_lesson, False, padding=8) vbox = gtk.VBox(False) vbox.pack_start(timer_hbox, padding=8) timer_box.add(vbox) inner_table.attach(timer_box, 1,2,1,2,gtk.FILL|gtk.EXPAND, gtk.FILL) #panel.pack_start(lang_box, expand=False, fill=False) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel() self.buddy_panel.show() if not parent._shared_activity: self.do_select_category(self) else: self.set_message(_("Waiting for remote game...")) # Contest mode flags self.set_contest_mode(False) self._on_lesson_plan = False
class SliderPuzzleUI (gtk.Table): __gsignals__ = {'game-state-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (int,))} def __init__(self, parent): super(SliderPuzzleUI, self).__init__(3,3,False) self._parent = parent # We want the translatables to be detected but not yet translated global _ _ = lambda x: x self.labels_to_translate = [] self._state = GAME_IDLE inner_table = gtk.Table(2,2,False) self.add(inner_table) self.game = SliderPuzzleWidget(9, GAME_SIZE, GAME_SIZE) self.game.connect("solved", self.do_solve) self.game.connect("moved", self.slider_move_cb) self._parent.connect("key_press_event",self.game.process_key) self._parent.connect("key_press_event",self.process_key) self.game.show() desktop = BorderFrame(border_color=COLOR_FRAME_CONTROLS) desktop.show() desktop.add(self.game) self.game_wrapper = gtk.VBox() self.game_wrapper.show() inner = gtk.HBox() inner.show() #BorderFrame(border=BORDER_ALL_BUT_BOTTOM, # border_color=COLOR_FRAME_CONTROLS, # bg_color=COLOR_BG_CONTROLS) inner.pack_start(desktop, expand=True, fill=False) self.game_wrapper.pack_start(inner, expand=True, fill=False) # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = gtk.VBox() # Logo image img_logo = gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, expand=False, fill=False) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = gtk.VBox() control_panel.add(control_panel_box) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # ... # Slice buttons btn_box = gtk.Table(1,5,False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) btn_box.attach(gtk.Label(), 0,1,0,2) #spacer = gtk.Label() #spacer.set_size_request(-1, 15) #control_panel_box.pack_start(spacer, expand=False, fill=False) #cutter = gtk.HBox(False, 8) #cutter.pack_start(gtk.Label(), True) self.btn_9 = prepare_btn(gtk.ToggleButton("9"),SLICE_BTN_WIDTH) self.btn_9.set_active(True) self.btn_9.connect("clicked", self.set_nr_pieces, 9) btn_box.attach(self.btn_9, 1,2,0,1,0,0) #cutter.pack_start(self.btn_9, False, False) self.btn_12 = prepare_btn(gtk.ToggleButton("12"), SLICE_BTN_WIDTH) self.btn_12.connect("clicked", self.set_nr_pieces, 12) btn_box.attach(self.btn_12, 2,3,0,1,0,0) #cutter.pack_start(self.btn_12, False, False) self.btn_16 = prepare_btn(gtk.ToggleButton("16"), SLICE_BTN_WIDTH) self.btn_16.connect("clicked", self.set_nr_pieces, 16) btn_box.attach(self.btn_16, 3,4,0,1,0,0) #cutter.pack_start(self.btn_16, False, False) #cutter.pack_start(gtk.Label(), True) #control_panel_box.pack_start(cutter, True) #spacer = gtk.Label() #spacer.set_size_request(-1, 10) #control_panel_box.pack_start(spacer, False) btn_box.attach(gtk.Label(), 4,5,0,1) control_panel_box.pack_start(btn_box, expand=False) self.thumb = ImageSelectorWidget(self._parent,frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, image_dir='images') self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.set_nr_pieces) control_panel_box.pack_start(self.thumb, False) spacer = gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, expand=False, fill=False) # The game control buttons btn_box = gtk.Table(3,3,False) btn_box.set_row_spacings(2) btn_box.attach(gtk.Label(), 0,1,0,3) btn_box.attach(gtk.Label(), 2,3,0,3) self.btn_solve = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1,2,0,1,0,0) self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1,2,1,2,0,0) self.btn_add = prepare_btn(gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1,2,2,3,0,0) control_panel_box.pack_start(btn_box, False) # Control panel end panel.pack_start(control_panel, expand=True, fill=True) inner_table.attach(panel, 0,1,0,1,0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game_wrapper) lang_combo = prepare_btn(LanguageComboBox('org.worldwideworkshop.olpc.SliderPuzzle')) lang_combo.connect('changed', self.do_select_language) # Push the gettext translator into the global namespace del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = gtk.HBox(False) vbox = gtk.VBox(False) vbox.pack_start(lang_combo, padding=8) hbox.pack_start(vbox, padding=8) lang_box.add(hbox) inner_table.attach(lang_box, 0,1,1,2,gtk.FILL, gtk.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, padding=8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True) self.notebook = gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box) inner_table.attach(self.notebook, 1,2,0,1, gtk.FILL, gtk.FILL) self.btn_lesson = prepare_btn(gtk.Button(" ")) self.labels_to_translate.append([self.btn_lesson, _("Lesson Plans")]) self.btn_lesson.connect("clicked", self.do_lesson_plan) timer_hbox.pack_start(self.btn_lesson, False, padding=8) vbox = gtk.VBox(False) vbox.pack_start(timer_hbox, padding=8) timer_box.add(vbox) inner_table.attach(timer_box, 1,2,1,2,gtk.FILL|gtk.EXPAND, gtk.FILL) #panel.pack_start(lang_box, expand=False, fill=False) self.do_select_language(lang_combo) self.buddy_panel = BuddyPanel() self.buddy_panel.show() if not parent._shared_activity: self.do_select_category(self) else: self.set_message(_("Waiting for remote game...")) # Contest mode flags self.set_contest_mode(False) self._on_lesson_plan = False def set_message (self, msg, frommesh=False): if frommesh and self.get_game_state() < GAME_STARTED: return self.msg_label.set_label(msg) def is_initiator (self): return self._parent.initiating def set_readonly (self, ro=True): self.thumb.set_readonly(ro) for b in (self.btn_9, self.btn_12, self.btn_16): if not b.get_active(): b.set_sensitive(False) @utils.trace def timer_toggle_cb (self, evt, running): logging.debug("Timer running: %s" % str(running)) if self._contest_mode and running: self.set_game_state(GAME_STARTED) self._send_status_update() #if self._contest_mode: # if running: # if self.game.filename and not self.game_wrapper.get_parent(): # self.game_box.pop() # else: # if not self.buddy_panel.get_parent(): # self.game_box.push(self.buddy_panel) def _set_control_area (self, *args): """ The controls area below the logo needs different actions when in contest mode, and also if we are the contest initiators or not. """ if self._contest_mode: if self.get_game_state() > GAME_IDLE: self.set_readonly() else: if self.is_initiator(): if self.timer.is_reset(): self.set_message(_("Select image and press Start Game...")) else: self.set_game_state(GAME_STARTED) else: self.set_message(_("Waiting for Puzzle image to be chosen...")) self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) def set_game_state (self, state, force=False): if state[0] > self._state[0] or force: self._state = state self.emit('game-state-changed', state[0]) self._set_control_area() if state == GAME_STARTED: self.set_button_translation(self.btn_add, "Buddies") self.btn_add.get_child().set_label(_("Buddies")) self._send_status_update() def get_game_state (self): return self._state def set_button_translation (self, btn, translation): for i in range(len(self.labels_to_translate)): if self.labels_to_translate[i][0] == btn: self.labels_to_translate[i][1] = translation break def set_contest_mode (self, mode): if getattr(self, '_contest_mode', None) != mode: self._contest_mode = bool(mode) self._set_control_area() if self._contest_mode: self.set_button_translation(self.btn_solve, "Give Up") self.btn_solve.get_child().set_label(_("Give Up")) self.set_button_translation(self.btn_shuffle, "Start Game") self.btn_shuffle.get_child().set_label(_("Start Game")) def is_contest_mode (self): return self._contest_mode# and self.game.filename def do_select_language (self, combo, *args): self.selected_lang_details = combo.translations[combo.get_active()] self.refresh_labels() def refresh_labels (self, first_time=False): self._parent.set_title(_("Slider Puzzle Activity")) for lbl in self.labels_to_translate: if isinstance(lbl[0], gtk.Button): lbl[0].get_child().set_label(_(lbl[1])) else: lbl[0].set_label(_(lbl[1])) if not self.game_wrapper.get_parent() and not first_time: self.game_box.pop() if self.notebook.get_current_page() == 1: m = self.do_lesson_plan else: m = self.do_select_category m(self) @utils.trace def set_nr_pieces (self, btn, nr_pieces=None): #if isinstance(btn, gtk.ToggleButton) and not btn.get_active(): # return if self.is_contest_mode() and isinstance(btn, gtk.ToggleButton) and nr_pieces == self.game.get_nr_pieces(): return if isinstance(btn, gtk.ToggleButton): if not btn.get_active(): if nr_pieces == self.game.get_nr_pieces(): logging.debug("A") btn.set_active(True) return if nr_pieces is None: nr_pieces = self.game.get_nr_pieces() if btn is None: #not isinstance(btn, gtk.ToggleButton): if self._contest_mode: self.set_game_state(GAME_STARTED) for n, b in ((9, self.btn_9),(12, self.btn_12),(16, self.btn_16)): if n == nr_pieces and not b.get_active(): logging.debug("B") b.set_sensitive(True) b.set_active(True) return if self.thumb.has_image(): if not self.game_wrapper.get_parent(): self.game_box.pop() self.game.load_image(self.thumb.get_image()) #self.thumb.set_game_widget(self.game) self.game.set_nr_pieces(nr_pieces) self.timer.reset(False) if isinstance(btn, gtk.ToggleButton): for n, b in ((9, self.btn_9),(12, self.btn_12),(16, self.btn_16)): if b is not btn: logging.debug("C") b.set_active(False) b.set_sensitive(not self._contest_mode) def do_shuffle (self, *args, **kwargs): if self._contest_mode: if self.get_game_state() > GAME_IDLE: # Restart self.set_game_state(GAME_STARTED, True) self._parent.frozen.thaw() self.timer.reset(True) elif self.game.filename is not None and self.timer.is_reset(): # Start self.timer.start() elif self.thumb.has_image(): if not self.game_wrapper.get_parent(): self.game_box.pop() self.game.load_image(self.thumb.get_image()) #self.thumb.set_game_widget(self.game) self.game.randomize() self.timer.reset(False) def slider_move_cb (self, *args): if not self.timer.is_running(): self.timer.start() def do_solve (self, btn): if self.game.filename is not None: if not self.game_wrapper.get_parent(): self.game_box.pop() self.game.show_image() self.timer.stop(True) if self._contest_mode and self.get_game_state() == GAME_STARTED: if btn != self.btn_solve: self.set_game_state(GAME_FINISHED) self.set_message(_("Puzzle Solved!")) else: self.set_game_state(GAME_QUIT) self.set_message(_("Gave Up")) self._set_control_area() # @utils.trace # def do_select_category(self, owner, *args, **kwargs): # if isinstance(owner, CategorySelector): # self.thumb.set_image_dir(args[0]) # #self.game_box.pop() # if not self.thumb.category.has_images(): # self.do_add_image(None) # else: # if self.game_wrapper.get_parent(): # s = CategorySelector("images", _("Choose a Subject"), self.thumb.get_image_dir()) # s.connect("selected", self.do_select_category) # s.show() # self.game_box.push(s) # s.grab_focus() # else: # self.game_box.pop() def do_select_category (self, o, *args): if isinstance(o, CategorySelector): self.thumb.set_image_dir(args[0]) #if not self.thumb.category.has_images(): # self.do_add_image(None) else: if self.game_wrapper.get_parent(): logging.debug("Current cat dir=%s" % self.thumb.get_image_dir()) s = CategorySelector(_("Choose a Subject"), self.thumb.get_image_dir(), path="images") #extra=('images/Sequencing Puzzles',)) s.connect("selected", self.do_select_category) s.show() self.game_box.push(s) s.grab_focus() else: self.game_box.pop() @utils.trace def do_add_image (self, widget, *args): """ Use to trigger and process the My Own Image selector. Also used for showing the buddies panel on contest mode""" if self._contest_mode and self.get_game_state() >= GAME_STARTED: # Buddy Panel if not self.buddy_panel.get_parent(): self.timer.stop() self.game_box.push(self.buddy_panel) else: self.game_box.pop() elif self._contest_mode and not self.is_initiator(): # do nothing pass else: self.thumb.add_image() self.do_shuffle() #if response is None: # else: # # My Own Image selector # imgfilter = gtk.FileFilter() # imgfilter.set_name(_("Image Files")) # imgfilter.add_mime_type('image/*') # fd = gtk.FileChooserDialog(title=_("Select Image File"), parent=self._parent, # action=gtk.FILE_CHOOSER_ACTION_OPEN, # buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) # # fd.set_current_folder(os.path.expanduser("~/")) # fd.set_modal(True) # fd.add_filter(imgfilter) # fd.connect("response", self.do_add_image) # fd.resize(800,600) # fd.show() #else: # if response == gtk.RESPONSE_ACCEPT: # if self.thumb.load_image(widget.get_filename()): # self.do_shuffle() # else: # err = gtk.MessageDialog(self._parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, # _("Not a valid image file")) # err.run() # err.destroy() # return # widget.destroy() def do_lesson_plan (self, btn): if self._on_lesson_plan: return try: self._on_lesson_plan = True if self._contest_mode and self.get_game_state() < GAME_STARTED: return page = self.notebook.get_current_page() if page == 0: self.timer.stop() self.timer.props.sensitive = False if self.notebook.get_n_pages() == 1: lessons = NotebookReaderWidget('lessons', self.selected_lang_details) lessons.connect('parent-set', self.do_lesson_plan_reparent) lessons.show_all() self.notebook.append_page(lessons) else: self.timer.props.sensitive = True self.notebook.set_current_page(int(not page)) finally: self._on_lesson_plan = False def do_lesson_plan_reparent (self, widget, oldparent): if widget.parent is None: self.set_button_translation(self.btn_lesson, "Lesson Plans") self.btn_lesson.get_child().set_label(_("Lesson Plans")) else: self.set_button_translation(self.btn_lesson, "Close Lesson") self.btn_lesson.get_child().set_label(_("Close Lesson")) def process_key (self, w, e): """ The callback for key processing. The button shortcuts are all defined here. """ k = gtk.gdk.keyval_name(e.keyval) if not isinstance(self._parent.get_focus(), gtk.Editable): if k == '1': self.btn_9.clicked() return True if k == '2': self.btn_12.clicked() return True if k == '3': self.btn_16.clicked() return True if k == 'period': self.thumb.next() return True if k == 'comma': self.thumb.previous() return True if k == 'Return': self.set_nr_pieces(None) return True if k == 'slash': self.do_select_category(None) return True if k == 'question': self.btn_add.clicked() return True if k == 'equal': self.btn_solve.clicked() return True if k in ('Escape', 'q'): gtk.main_quit() return True return False @utils.trace def _freeze (self, journal=True): """ returns a json writable object representation capable of being used to restore our current status """ return (self.thumb._freeze(), self.game._freeze(journal=journal), self.game.get_nr_pieces(), self.timer._freeze()) def _thaw (self, obj): """ retrieves a frozen status from a python object, as per _freeze """ logging.debug('_thaw: %s' % obj) if not obj[1]['image']: return if not obj[1].has_key('image'): self.game.load_image(self.thumb.get_image()) self.set_nr_pieces(None, obj[2]) logging.debug(obj[1].keys()) wimg = obj[1].has_key('image') self.game._thaw(obj[1]) if wimg: logging.debug("Forcing thumb image from the one in game") self.thumb.load_pb(self.game.image) self.timer.reset() self.timer._thaw(obj[3]) self.game_box.pop() @utils.trace def _send_status_update (self): """ Send a status update signal """ if self._parent._shared_activity: if self.get_game_state() == GAME_STARTED: if self.thumb.has_image(): self.set_message(_("Game Started!")) self._parent.game_tube.StatusUpdate(self._state[1], self.timer.is_running(), self.timer.ellapsed())
def __init__(self, parent): super(SliderPuzzleUI, self).__init__(3, 3, False) self._parent = parent # We want the translatables to be detected but not yet translated global _ def _(x): return x self.labels_to_translate = [] self._state = GAME_IDLE inner_table = Gtk.Table(2, 2, False) self.add(inner_table) self.from_journal = False self.game = SliderPuzzleWidget(9, GAME_SIZE, GAME_SIZE) self.game.connect("solved", self.do_solve) self.game.connect("moved", self.slider_move_cb) self._parent.connect("key_press_event", self.game.process_key) self._parent.connect("key_press_event", self.process_key) self.game.show() desktop = BorderFrame(border_color=COLOR_FRAME_CONTROLS) desktop.show() desktop.add(self.game) self.game_wrapper = Gtk.VBox() self.game_wrapper.show() inner = Gtk.HBox() inner.show() inner.pack_start(desktop, True, False, 0) self.game_wrapper.pack_start(inner, True, False, 0) # panel is a holder for everything on the left side down to (not inclusive) the language dropdown panel = Gtk.VBox() # Logo image img_logo = Gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() panel.pack_start(img_logo, False, False, 0) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) control_panel_box = Gtk.VBox() control_panel.add(control_panel_box) spacer = Gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, False, False, 0) self.thumb = ImageSelectorWidget(self._parent, frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, image_dir='images') control_panel_box.pack_start(self.thumb, False, True, 0) spacer = Gtk.Label() spacer.set_size_request(-1, 5) control_panel_box.pack_start(spacer, False, False, 0) # Control panel end panel.pack_start(control_panel, True, True, 0) inner_table.attach(panel, 0, 1, 0, 1, 0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game_wrapper) lang_combo = prepare_btn( LanguageComboBox('org.worldwideworkshop.olpc.SliderPuzzle')) del _ lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) hbox = Gtk.HBox(False) vbox = Gtk.VBox(False) vbox.pack_start(lang_combo, True, True, 8) hbox.pack_start(vbox, True, True, 8) lang_box.add(hbox) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) timer_hbox = Gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) timer_hbox.pack_start(self.timer, False, True, 8) self.timer.connect('timer_toggle', self.timer_toggle_cb) self.msg_label = Gtk.Label() self.msg_label.show() timer_hbox.pack_start(self.msg_label, True, True, 0) self.notebook = Gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.notebook.append_page(self.game_box, None) inner_table.attach(self.notebook, 1, 2, 0, 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL) vbox = Gtk.VBox(False) vbox.pack_start(timer_hbox, True, True, 8) timer_box.add(vbox) inner_table.attach(timer_box, 1, 2, 1, 2, Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, Gtk.AttachOptions.FILL) self.buddy_panel = BuddyPanel() self.buddy_panel.show() # Contest mode flags self.set_contest_mode(False) self.initial_path = os.path.join(get_bundle_path(), 'images', 'image_aisc_h250_w313_lg.gif') self.set_nr_pieces(nr_pieces=9, path=self.initial_path) self.pre_path = self.initial_path self._on_lesson_plan = False