def __init__(self, handle):
        super(ImplodeActivity, self).__init__(handle)

        _logger.debug('Starting implode activity...')

        self.max_participants = 1

        self._game = ImplodeGame()

        game_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        game_box.pack_start(self._game, True, True, 0)
        self._stuck_strip = _StuckStrip()

        self._configure_toolbars()

        self.set_canvas(game_box)

        # Show everything except the stuck strip.
        self.show_all()
        self._configure_cb()

        game_box.pack_end(self._stuck_strip,
                          expand=False,
                          fill=False,
                          padding=0)

        self._game.connect('show-stuck', self._show_stuck_cb)
        self._stuck_strip.connect('undo-clicked', self._stuck_undo_cb)
        game_box.connect('key-press-event', self._key_press_event_cb)

        self._game.grab_focus()

        last_game_path = self._get_last_game_path()
        if os.path.exists(last_game_path):
            self.read_file(last_game_path)
    def __init__(self, handle):
        super(ImplodeActivity, self).__init__(handle)

        _logger.debug('Starting implode activity...')

        self.max_participants = 1

        self._game = ImplodeGame()

        game_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        game_box.pack_start(self._game, True, True, 0)
        self._stuck_strip = _StuckStrip()

        self._configure_toolbars()

        self.set_canvas(game_box)

        # Show everything except the stuck strip.
        self.show_all()
        self._configure_cb()

        game_box.pack_end(self._stuck_strip, expand=False, fill=False, padding=0)

        self._game.connect('show-stuck', self._show_stuck_cb)
        self._stuck_strip.connect('undo-clicked', self._stuck_undo_cb)
        game_box.connect('key-press-event', self._key_press_event_cb)

        self._game.grab_focus()

        last_game_path = self._get_last_game_path()
        if os.path.exists(last_game_path):
            self.read_file(last_game_path)
    def __init__(self, handle):
        Activity.__init__(self, handle)

        self._joining_hide = False
        self._game = ImplodeGame()
        self._collab = CollabWrapper(self)
        self._collab.connect('message', self._message_cb)

        game_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        game_box.pack_start(self._game, True, True, 0)
        self._stuck_strip = _StuckStrip()

        self._configure_toolbars()

        self.set_canvas(game_box)

        # Show everything except the stuck strip.
        self.show_all()
        self._configure_cb()

        game_box.pack_end(self._stuck_strip,
                          expand=False,
                          fill=False,
                          padding=0)

        self._game.connect('show-stuck', self._show_stuck_cb)
        self._game.connect('piece-selected', self._piece_selected_cb)
        self._game.connect('undo-key-pressed', self._undo_key_pressed_cb)
        self._game.connect('redo-key-pressed', self._redo_key_pressed_cb)
        self._game.connect('new-key-pressed', self._new_key_pressed_cb)
        self._stuck_strip.connect('undo-clicked', self._stuck_undo_cb)
        game_box.connect('key-press-event', self._key_press_event_cb)

        self._game.grab_focus()

        last_game_path = self._get_last_game_path()
        if os.path.exists(last_game_path):
            self.read_file(last_game_path)

        self._collab.setup()

        # Hide the canvas when joining a shared activity
        if self.shared_activity:
            if not self.get_shared():
                self.get_canvas().hide()
                self.busy()
                self._joining_hide = True
class ImplodeActivity(Activity):
    def __init__(self, handle):
        super(ImplodeActivity, self).__init__(handle)

        _logger.debug('Starting implode activity...')

        self.max_participants = 1

        self._game = ImplodeGame()

        game_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        game_box.pack_start(self._game, True, True, 0)
        self._stuck_strip = _StuckStrip()

        self._configure_toolbars()

        self.set_canvas(game_box)

        # Show everything except the stuck strip.
        self.show_all()
        self._configure_cb()

        game_box.pack_end(self._stuck_strip, expand=False, fill=False, padding=0)

        self._game.connect('show-stuck', self._show_stuck_cb)
        self._stuck_strip.connect('undo-clicked', self._stuck_undo_cb)
        game_box.connect('key-press-event', self._key_press_event_cb)

        self._game.grab_focus()

        last_game_path = self._get_last_game_path()
        if os.path.exists(last_game_path):
            self.read_file(last_game_path)

    def _get_last_game_path(self):
        return os.path.join(self.get_activity_root(), 'data', 'last_game')

    def read_file(self, file_path):
        # Loads the game state from a file.
        f = file(file_path, 'rt')
        content = f.read()
        io = StringIO(content)
        file_data = json.load(io)
        f.close()

        # print file_data
        # _logger.debug(file_data)
        (file_type, version, game_data) = file_data
        if file_type == 'Implode save game' and version <= [1, 0]:
            self._game.set_game_state(game_data)
            # Ensure that the visual display matches the game state. <MS>
            self._levels_buttons[game_data['difficulty']].props.active = True

    def write_file(self, file_path):
        # Writes the game state to a file.
        game_data = self._game.get_game_state()
        file_data = ['Implode save game', [1, 0], game_data]
        last_game_path = self._get_last_game_path()
        for path in (file_path, last_game_path):
            f = file(path, 'wt')
            io = StringIO()
            json.dump(file_data,io)
            content = io.getvalue()
            f.write(content)
            f.close()

    def _show_stuck_cb(self, state, data=None):
        if data:
            self._stuck_strip.show_all()
        else:
            if self._stuck_strip.get_focus_child():
                self._game.grab_focus()
            self._stuck_strip.hide()

    def _stuck_undo_cb(self, state, data=None):
        self._game.undo_to_solvable_state()

    def _key_press_event_cb(self, source, event):
        # Make the game navigable by keypad controls.
        action = KEY_MAP.get(event.keyval, None)
        if action is None:
            return False
        if not self._stuck_strip.get_state_flags() & Gtk.AccelFlags.VISIBLE:
            return True
        if self._game.get_focus_child():
            if action == 'down':
                self._stuck_strip.button.grab_focus()
            return True
        elif self._stuck_strip.get_focus_child():
            if action == 'up':
                self._game.grab_focus()
            elif action == 'select':
                self._stuck_strip.button.activate()
            return True
        return True

    def _configure_toolbars(self):
        """Create, set, and show a toolbar box with an activity button, game
        controls, difficulty selector, help button, and stop button. All
        callbacks are locally defined."""

        self._seps = []

        toolbar_box = ToolbarBox()
        toolbar = toolbar_box.toolbar

        activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        self._add_separator(toolbar)

        def add_button(icon_name, tooltip, func):
            def callback(source):
                func()
            button = ToolButton(icon_name)
            toolbar.add(button)
            button.connect('clicked', callback)
            button.set_tooltip(tooltip)

        add_button('new-game'   , _("New")   , self._game.new_game)
        add_button('replay-game', _("Replay"), self._game.replay_game)

        self._add_separator(toolbar)

        add_button('edit-undo'  , _("Undo")  , self._game.undo)
        add_button('edit-redo'  , _("Redo")  , self._game.redo)

        self._add_separator(toolbar)

        self._levels_buttons = []
        def add_level_button(icon_name, tooltip, numeric_level):
            if self._levels_buttons:
                button = RadioToolButton(icon_name=icon_name,
                                         group=self._levels_buttons[0])
            else:
                button = RadioToolButton(icon_name=icon_name)
            self._levels_buttons.append(button)
            toolbar.add(button)

            def callback(source):
                if source.get_active():
                    self._game.set_level(numeric_level)
                    self._game.new_game()

            button.connect('clicked', callback)
            button.set_tooltip(tooltip)

        add_level_button('easy-level'  , _("Easy")  , 0)
        add_level_button('medium-level', _("Medium"), 1)
        add_level_button('hard-level'  , _("Hard")  , 2)

        self._add_separator(toolbar)

        def _help_clicked_cb():
            help_window = _HelpWindow()
            help_window.set_transient_for(self.get_toplevel())
            help_window.show_all()

        # NOTE: Naming the icon "help" instead of "help-icon" seems to use a
        # GTK stock icon instead of our custom help; the stock icon may be more
        # desireable in the future.  It doesn't seem to be themed for Sugar
        # right now, however.
        add_button('toolbar-help', _("Help"), _help_clicked_cb)

        self._add_expander(toolbar)

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>Q'
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

    def _add_separator(self, toolbar):
        self._seps.append(Gtk.SeparatorToolItem())
        toolbar.add(self._seps[-1])
        self._seps[-1].show()

    def _add_expander(self, toolbar, expand=True):
        """Insert a toolbar item which will expand to fill the available
        space."""
        self._seps.append(Gtk.SeparatorToolItem())
        self._seps[-1].props.draw = False
        self._seps[-1].set_expand(expand)
        toolbar.insert(self._seps[-1], -1)
        self._seps[-1].show()

    def _configure_cb(self, event=None):
        if Gdk.Screen.width() < Gdk.Screen.height():
            _logger.debug('TRUE')
            hide = True
        else:
            _logger.debug('FALSE')
            hide = False
        for sep in self._seps:
            if hide:
                sep.hide()
            else:
                sep.show()
class ImplodeActivity(Activity):
    def __init__(self, handle):
        Activity.__init__(self, handle)

        self._joining_hide = False
        self._game = ImplodeGame()
        self._collab = CollabWrapper(self)
        self._collab.connect('message', self._message_cb)

        game_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        game_box.pack_start(self._game, True, True, 0)
        self._stuck_strip = _StuckStrip()

        self._configure_toolbars()

        self.set_canvas(game_box)

        # Show everything except the stuck strip.
        self.show_all()
        self._configure_cb()

        game_box.pack_end(self._stuck_strip,
                          expand=False,
                          fill=False,
                          padding=0)

        self._game.connect('show-stuck', self._show_stuck_cb)
        self._game.connect('piece-selected', self._piece_selected_cb)
        self._game.connect('undo-key-pressed', self._undo_key_pressed_cb)
        self._game.connect('redo-key-pressed', self._redo_key_pressed_cb)
        self._game.connect('new-key-pressed', self._new_key_pressed_cb)
        self._stuck_strip.connect('undo-clicked', self._stuck_undo_cb)
        game_box.connect('key-press-event', self._key_press_event_cb)

        self._game.grab_focus()

        last_game_path = self._get_last_game_path()
        if os.path.exists(last_game_path):
            self.read_file(last_game_path)

        self._collab.setup()

        # Hide the canvas when joining a shared activity
        if self.shared_activity:
            if not self.get_shared():
                self.get_canvas().hide()
                self.busy()
                self._joining_hide = True

    def _get_last_game_path(self):
        return os.path.join(self.get_activity_root(), 'data', 'last_game')

    def get_data(self):
        return self._game.get_game_state()

    def set_data(self, data):
        if not data['win_draw_flag']:
            self._game.set_game_state(data)
        # Ensure that the visual display matches the game state.
        self._levels_buttons[data['difficulty']].props.active = True
        # Release the cork
        if self._joining_hide:
            self.get_canvas().show()
            self.unbusy()

    def read_file(self, file_path):
        # Loads the game state from a file.
        f = open(file_path, 'r')
        file_data = json.loads(f.read())
        f.close()

        (file_type, version, game_data) = file_data
        if file_type == 'Implode save game' and version <= [1, 0]:
            self.set_data(game_data)

    def write_file(self, file_path):
        # Writes the game state to a file.
        data = self.get_data()
        file_data = ['Implode save game', [1, 0], data]
        last_game_path = self._get_last_game_path()
        for path in (file_path, last_game_path):
            f = open(path, 'w')
            f.write(json.dumps(file_data))
            f.close()

    def _show_stuck_cb(self, state, data=None):
        if self.shared_activity:
            return
        if self.metadata:
            share_scope = self.metadata.get('share-scope', SCOPE_PRIVATE)
            if share_scope != SCOPE_PRIVATE:
                return
        if data:
            self._stuck_strip.show_all()
        else:
            if self._stuck_strip.get_focus_child():
                self._game.grab_focus()
            self._stuck_strip.hide()

    def _stuck_undo_cb(self, state, data=None):
        self._game.undo_to_solvable_state()

    def _key_press_event_cb(self, source, event):
        # Make the game navigable by keypad controls.
        action = KEY_MAP.get(event.keyval, None)
        if action is None:
            return False
        if not self._stuck_strip.get_state_flags() & Gtk.AccelFlags.VISIBLE:
            return True
        if self._game.get_focus_child():
            if action == 'down':
                self._stuck_strip.button.grab_focus()
            return True
        elif self._stuck_strip.get_focus_child():
            if action == 'up':
                self._game.grab_focus()
            elif action == 'select':
                self._stuck_strip.button.activate()
            return True
        return True

    def _configure_toolbars(self):
        """Create, set, and show a toolbar box with an activity button, game
        controls, difficulty selector, help button, and stop button. All
        callbacks are locally defined."""

        self._seps = []

        toolbar_box = ToolbarBox()
        toolbar = toolbar_box.toolbar

        activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        self._add_separator(toolbar)

        def add_button(icon_name, tooltip, callback):
            button = ToolButton(icon_name)
            toolbar.add(button)
            button.connect('clicked', callback)
            button.set_tooltip(tooltip)
            return button

        add_button('new-game', _("New"), self._new_game_cb)
        add_button('replay-game', _("Replay"), self._replay_game_cb)

        self._add_separator(toolbar)

        add_button('edit-undo', _("Undo"), self._undo_cb)
        add_button('edit-redo', _("Redo"), self._redo_cb)

        self._add_separator(toolbar)

        self._levels_buttons = []

        def add_level_button(icon_name, tooltip, numeric_level):
            if self._levels_buttons:
                button = RadioToolButton(icon_name=icon_name,
                                         group=self._levels_buttons[0])
            else:
                button = RadioToolButton(icon_name=icon_name)
            self._levels_buttons.append(button)
            toolbar.add(button)

            def callback(source):
                if source.get_active():
                    self._collab.post({'action': icon_name})
                    self._game.set_level(numeric_level)
                    self._game.new_game()

            button.connect('toggled', callback)
            button.set_tooltip(tooltip)

        add_level_button('easy-level', _("Easy"), 0)
        add_level_button('medium-level', _("Medium"), 1)
        add_level_button('hard-level', _("Hard"), 2)

        self._add_separator(toolbar)

        def _help_clicked_cb(button):
            help_window = _HelpWindow()
            help_window.set_transient_for(self.get_toplevel())
            help_window.show_all()

        help_button = add_button('toolbar-help', _("Help"), _help_clicked_cb)

        def _help_disable_cb(collab, buddy):
            if help_button.props.sensitive:
                help_button.props.sensitive = False

        self._collab.connect('buddy-joined', _help_disable_cb)

        self._add_expander(toolbar)

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

    def _add_separator(self, toolbar):
        self._seps.append(Gtk.SeparatorToolItem())
        toolbar.add(self._seps[-1])
        self._seps[-1].show()

    def _add_expander(self, toolbar, expand=True):
        """Insert a toolbar item which will expand to fill the available
        space."""
        self._seps.append(Gtk.SeparatorToolItem())
        self._seps[-1].props.draw = False
        self._seps[-1].set_expand(expand)
        toolbar.insert(self._seps[-1], -1)
        self._seps[-1].show()

    def _configure_cb(self, event=None):
        if Gdk.Screen.width() < Gdk.Screen.height():
            hide = True
        else:
            hide = False
        for sep in self._seps:
            if hide:
                sep.hide()
            else:
                sep.show()

    def _new_game_cb(self, button):
        self._game.reseed()
        self._collab.post({
            'action': 'new-game',
            'seed': self._game.get_seed()
        })
        self._game.new_game()

    def _replay_game_cb(self, button):
        self._collab.post({'action': 'replay-game'})
        self._game.replay_game()

    def _undo_cb(self, button):
        self._collab.post({'action': 'edit-undo'})
        self._game.undo()

    def _redo_cb(self, button):
        self._collab.post({'action': 'edit-redo'})
        self._game.redo()

    def _message_cb(self, collab, buddy, msg):
        action = msg.get('action')
        if action == 'new-game':
            self._game.set_seed(msg.get('seed'))
            self._game.new_game()
        elif action == 'replay-game':
            self._game.replay_game()
        elif action == 'edit-undo':
            self._game.undo()
        elif action == 'edit-redo':
            self._game.redo()
        elif action == 'easy-level':
            self._game.set_level(0)
            self._game.new_game()
        elif action == 'medium-level':
            self._game.set_level(1)
            self._game.new_game()
        elif action == 'hard-level':
            self._game.set_level(2)
            self._game.new_game()
        elif action == 'piece-selected':
            x = msg.get('x')
            y = msg.get('y')
            self._game.piece_selected(x, y)

    def _piece_selected_cb(self, game, x, y):
        self._collab.post({'action': 'piece-selected', 'x': x, 'y': y})

    def _undo_key_pressed_cb(self, game, dummy):
        self._collab.post({'action': 'edit-undo'})

    def _redo_key_pressed_cb(self, game, dummy):
        self._collab.post({'action': 'edit-redo'})

    def _new_key_pressed_cb(self, game, seed):
        self._collab.post({'action': 'new-game', 'seed': seed})
class ImplodeActivity(Activity):
    def __init__(self, handle):
        super(ImplodeActivity, self).__init__(handle)

        _logger.debug('Starting implode activity...')

        self.max_participants = 1

        self._game = ImplodeGame()

        game_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        game_box.pack_start(self._game, True, True, 0)
        self._stuck_strip = _StuckStrip()

        self._configure_toolbars()

        self.set_canvas(game_box)

        # Show everything except the stuck strip.
        self.show_all()
        self._configure_cb()

        game_box.pack_end(self._stuck_strip,
                          expand=False,
                          fill=False,
                          padding=0)

        self._game.connect('show-stuck', self._show_stuck_cb)
        self._stuck_strip.connect('undo-clicked', self._stuck_undo_cb)
        game_box.connect('key-press-event', self._key_press_event_cb)

        self._game.grab_focus()

        last_game_path = self._get_last_game_path()
        if os.path.exists(last_game_path):
            self.read_file(last_game_path)

    def _get_last_game_path(self):
        return os.path.join(self.get_activity_root(), 'data', 'last_game')

    def read_file(self, file_path):
        # Loads the game state from a file.
        f = open(file_path, 'rt')
        content = f.read()
        io = StringIO(content)
        file_data = json.load(io)
        f.close()

        # print file_data
        # _logger.debug(file_data)
        (file_type, version, game_data) = file_data
        if file_type == 'Implode save game' and version <= [1, 0]:
            if not game_data['win_draw_flag']:
                self._game.set_game_state(game_data)
            # Ensure that the visual display matches the game state.
            self._levels_buttons[game_data['difficulty']].props.active = True

    def write_file(self, file_path):
        # Writes the game state to a file.
        game_data = self._game.get_game_state()
        file_data = ['Implode save game', [1, 0], game_data]
        last_game_path = self._get_last_game_path()
        for path in (file_path, last_game_path):
            f = open(path, 'wt')
            io = StringIO()
            json.dump(file_data, io)
            content = io.getvalue()
            f.write(content)
            f.close()

    def _show_stuck_cb(self, state, data=None):
        if data:
            self._stuck_strip.show_all()
        else:
            if self._stuck_strip.get_focus_child():
                self._game.grab_focus()
            self._stuck_strip.hide()

    def _stuck_undo_cb(self, state, data=None):
        self._game.undo_to_solvable_state()

    def _key_press_event_cb(self, source, event):
        # Make the game navigable by keypad controls.
        action = KEY_MAP.get(event.keyval, None)
        if action is None:
            return False
        if not self._stuck_strip.get_state_flags() & Gtk.AccelFlags.VISIBLE:
            return True
        if self._game.get_focus_child():
            if action == 'down':
                self._stuck_strip.button.grab_focus()
            return True
        elif self._stuck_strip.get_focus_child():
            if action == 'up':
                self._game.grab_focus()
            elif action == 'select':
                self._stuck_strip.button.activate()
            return True
        return True

    def _configure_toolbars(self):
        """Create, set, and show a toolbar box with an activity button, game
        controls, difficulty selector, help button, and stop button. All
        callbacks are locally defined."""

        self._seps = []

        toolbar_box = ToolbarBox()
        toolbar = toolbar_box.toolbar

        activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        self._add_separator(toolbar)

        def add_button(icon_name, tooltip, func):
            def callback(source):
                func()

            button = ToolButton(icon_name)
            toolbar.add(button)
            button.connect('clicked', callback)
            button.set_tooltip(tooltip)

        add_button('new-game', _("New"), self._game.new_game)
        add_button('replay-game', _("Replay"), self._game.replay_game)

        self._add_separator(toolbar)

        add_button('edit-undo', _("Undo"), self._game.undo)
        add_button('edit-redo', _("Redo"), self._game.redo)

        self._add_separator(toolbar)

        self._levels_buttons = []

        def add_level_button(icon_name, tooltip, numeric_level):
            if self._levels_buttons:
                button = RadioToolButton(icon_name=icon_name,
                                         group=self._levels_buttons[0])
            else:
                button = RadioToolButton(icon_name=icon_name)
            self._levels_buttons.append(button)
            toolbar.add(button)

            def callback(source):
                if source.get_active():
                    self._game.set_level(numeric_level)
                    self._game.new_game()

            button.connect('toggled', callback)
            button.set_tooltip(tooltip)

        add_level_button('easy-level', _("Easy"), 0)
        add_level_button('medium-level', _("Medium"), 1)
        add_level_button('hard-level', _("Hard"), 2)

        self._add_separator(toolbar)

        def _help_clicked_cb():
            help_window = _HelpWindow()
            help_window.set_transient_for(self.get_toplevel())
            help_window.show_all()

        add_button('toolbar-help', _("Help"), _help_clicked_cb)

        self._add_expander(toolbar)

        stop_button = StopButton(self)
        stop_button.props.accelerator = '<Ctrl>Q'
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show()

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

    def _add_separator(self, toolbar):
        self._seps.append(Gtk.SeparatorToolItem())
        toolbar.add(self._seps[-1])
        self._seps[-1].show()

    def _add_expander(self, toolbar, expand=True):
        """Insert a toolbar item which will expand to fill the available
        space."""
        self._seps.append(Gtk.SeparatorToolItem())
        self._seps[-1].props.draw = False
        self._seps[-1].set_expand(expand)
        toolbar.insert(self._seps[-1], -1)
        self._seps[-1].show()

    def _configure_cb(self, event=None):
        if Gdk.Screen.width() < Gdk.Screen.height():
            _logger.debug('TRUE')
            hide = True
        else:
            _logger.debug('FALSE')
            hide = False
        for sep in self._seps:
            if hide:
                sep.hide()
            else:
                sep.show()