[gnome-games/sudoku-tube] Make tracker working



commit b14df4da6e75ab35bbd6391b79c07c37e60a5d92
Author: Zhang Sen <zh jesse gmail com>
Date:   Sun Jul 12 21:11:25 2009 +0800

    Make tracker working
    
    * Again undo/redo is not working
    * Don't understand what trackers_for_point() is for

 gnome-sudoku/src/lib/gsudoku.py     |  127 ++++-------------------------------
 gnome-sudoku/src/lib/main.py        |    2 +-
 gnome-sudoku/src/lib/tracker_box.py |  103 ++++++++++++++++++++++++----
 3 files changed, 104 insertions(+), 128 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/gsudoku.py b/gnome-sudoku/src/lib/gsudoku.py
index b1c8084..919f89c 100644
--- a/gnome-sudoku/src/lib/gsudoku.py
+++ b/gnome-sudoku/src/lib/gsudoku.py
@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 import math
-import random
 
 import gtk
 import gobject
@@ -9,20 +8,6 @@ import colors
 import number_box
 import sudoku
 
-TRACKER_COLORS = [
-    # Use tango colors recommended here:
-    # http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
-    tuple([x / 255.0 for x in cols]) for cols in
-    [(32, 74, 135), # Sky Blue 3
-     (78, 154, 6), # Chameleon 3
-     (206, 92, 0), # Orange 3
-     (143, 89, 2), # Chocolate 3
-     (92, 53, 102), # Plum 3
-     (85, 87, 83), # Aluminium 5
-     (196, 160, 0), # Butter 3
-     ]
-    ]
-
 def gtkcolor_to_rgb (color):
     return (color.red   / float(2**16),
             color.green / float(2**16),
@@ -105,6 +90,9 @@ class SudokuNumberGrid (gtk.AspectFrame):
     def set_readonly_appearance(self, x, y, flag):
         self.__entries__[(x, y)].set_read_only(flag)
 
+    def set_color(self, x, y, color):
+        self.__entries__[(x, y)].set_color(color)
+
     def set_focus(self, x, y):
         self.table.set_focus_child(self.__entries__[x, y])
 
@@ -160,8 +148,13 @@ class ParallelDict (dict):
 
 class SudokuView(SudokuNumberGrid, gobject.GObject):
 
+    # some signals to give notice about change of the View
     __gsignals__ = {
-        'puzzle-finished':(gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())}
+            # atm. only used by dancer
+            "puzzle-finished": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+            # atm. only used by tracker
+            "view-updated": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
+                (int, int, int))}
 
     def __init__(self, group_size):
         SudokuNumberGrid.__init__(self, group_size)
@@ -197,6 +190,7 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
             x, y = box.x, box.y,
             if box.value is not None:
                 self.set_value(x, y, box.value)
+                self.emit("view-updated", x, y, box.value)
             if box.top_note is not None or box.bottom_note is not None:
                 self._set_notes(x, y, box.top_note, box.bottom_note)
             if box.conflict is not None:
@@ -212,7 +206,10 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
         self.__entries__[(x, y)].set_notes((top_note, bottom_note))
 
     def _number_changed_cb(self, widget, new_number):
-        self._model.set_value(widget.x, widget.y, new_number)
+        self.update_model(widget.x, widget.y, new_number)
+
+    def update_model(self, x, y, value):
+        self._model.set_value(x, y, value)
 
     def _notes_changed_cb(self, widget, top_note, bottom_note):
         self._model.set_notes(widget.x, widget.y, top_note, bottom_note)
@@ -320,7 +317,6 @@ class SudokuModel:
         self.show_impossible_implications = False
         self.impossible_hints = 0
         self.impossibilities = []
-        self.trackers = {}
         self.__trackers_tracking__ = {}
         self._setup_grid(grid, group_size)
 
@@ -411,8 +407,6 @@ class SudokuModel:
         self.auto_fills = 0
         self.hints = 0
         self.impossible_hints = 0
-        self.trackers = {}
-        self.__trackers_tracking__ = {}
         self._blank_grid()
         self._setup_grid(grid, group_size)
 
@@ -517,45 +511,6 @@ class SudokuModel:
     def _record_conflicts(self, x, y, new_conflicts):
         self.__error_pairs__[(x, y)] = new_conflicts
 
-    def add_value (self, x, y, val, trackers = []):
-        """Add value val at position x, y.
-
-        If tracker is True, we track it with tracker ID tracker.
-
-        Otherwise, we use any currently tracking trackers to track our addition.
-
-        Providing the tracker arg is mostly useful for e.g. undo/redo
-        or removed items.
-
-        To specify NO trackers, use trackers = [-1]
-        """
-        # Add the value to the UI to display
-        self.set_value(x, y, val)
-        if self.doing_initial_setup:
-            self.set_readonly_appearance(x, y, True)
-        # Handle any trackers.
-        if trackers:
-            # Explicitly specified tracker
-            for tracker in trackers:
-                if tracker == -1:
-                    pass
-                self.__entries__[(x, y)].set_color(self.get_tracker_color(tracker))
-                self.trackers[tracker].append((x, y, val))
-        elif True in self.__trackers_tracking__.values():
-            for k, v in self.__trackers_tracking__.items():
-                if v:
-                    self.__entries__[(x, y)].set_color(self.get_tracker_color(k))
-                    self.trackers[k].append((x, y, val))
-        # Add value to our underlying sudoku grid -- this will raise
-        # an error if the value is out of bounds with the current
-        # rules.
-        try:
-            self.grid.add(x, y, val, True)
-        except sudoku.ConflictError, err:
-            self._complain_conflicts(err.x, err.y, err.value)
-        # Draw our entry
-        self.__entries__[(x, y)].queue_draw()
-
     def remove (self, x, y, do_removal = False):
         """Remove x, y from our visible grid.
 
@@ -606,14 +561,6 @@ class SudokuModel:
                 self.__entries__[(x, y)].set_impossible(False)
         self.impossibilities = implications
 
-    def create_tracker (self, identifier = 0):
-        if not identifier:
-            identifier = 0
-        while self.trackers.has_key(identifier):
-            identifier += 1
-        self.trackers[identifier] = []
-        return identifier
-
     def _trackers_for_point(self, x, y, val = None):
         if val:
             # if we have a value we can do this a simpler way...
@@ -627,52 +574,6 @@ class SudokuModel:
                 self.trackers.items())
         return [t[0] for t in track_for_point]
 
-    def get_tracker_color (self, identifier):
-        if len(TRACKER_COLORS)>identifier:
-            return TRACKER_COLORS[identifier]
-        else:
-            random_color = TRACKER_COLORS[0]
-            while random_color in TRACKER_COLORS:
-                # If we have generated all possible colors, this will
-                # enter an infinite loop
-                random_color = (random.randint(0, 100)/100.0,
-                                random.randint(0, 100)/100.0,
-                                random.randint(0, 100)/100.0)
-            TRACKER_COLORS.append(random_color)
-            return self.get_tracker_color(identifier)
-
-    def toggle_tracker (self, identifier, value):
-        """Toggle tracking for tracker identified by identifier."""
-        self.__trackers_tracking__[identifier] = value
-
-    def delete_by_tracker (self, identifier):
-        """Delete all cells tracked by tracker ID identifer."""
-        ret = []
-        while self.trackers[identifier]:
-            x, y, v = self.trackers[identifier][0]
-            ret.append((x, y, v, self._trackers_for_point(x, y, v)))
-            self.remove(x, y)
-            if self.grid and self.grid._get_(x, y):
-                self.grid.remove(x, y)
-        return ret
-
-    def delete_except_for_tracker (self, identifier):
-        tracks = self.trackers[identifier]
-        removed = []
-        for x in range(self.group_size):
-            for y in range(self.group_size):
-                val = self.grid._get_(x, y)
-                if (val
-                    and (x, y, val) not in tracks
-                    and not self.grid.virgin._get_(x, y)
-                    ):
-                    removed.append((x, y, val, self._trackers_for_point(x, y, val)))
-                    self.remove(x, y)
-                    if self.grid and self.grid._get_(x, y):
-                        self.grid.remove(x, y)
-
-        return removed
-
     def add_tracker (self, x, y, tracker, val = None):
         self.__entries__[(x, y)].set_color(self.get_tracker_color(tracker))
         if not val:
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index e4680bd..99d721d 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -196,7 +196,7 @@ class UI (gconf_wrapper.GConfWrapper):
         self._main_grid_vew.connect('puzzle-finished', self.you_win_callback)
         main_grid_container.pack_start(self._main_grid_vew, padding=6)
 
-        self.tracker_ui = tracker_box.TrackerBox(self)
+        self.tracker_ui = tracker_box.TrackerBox(self._main_grid_vew)
         self.tracker_ui.hide()
         tracker_ui_container.pack_start(self.tracker_ui)
 
diff --git a/gnome-sudoku/src/lib/tracker_box.py b/gnome-sudoku/src/lib/tracker_box.py
index d81c484..2e0e712 100644
--- a/gnome-sudoku/src/lib/tracker_box.py
+++ b/gnome-sudoku/src/lib/tracker_box.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import os.path
+import random
 
 import gtk
 import gobject
@@ -35,7 +36,7 @@ class TrackerBox (gtk.VBox):
         self.builder = gtk.Builder()
         self.builder.add_from_file(os.path.join(defaults.UI_DIR,
             'tracker.ui'))
-        self.main_ui = main_ui
+        self._tracker_model = TrackerModel(main_ui)
         vbox = self.builder.get_object('vbox1')
         vbox.unparent()
         self.pack_start(vbox, expand = True, fill = True)
@@ -88,10 +89,10 @@ class TrackerBox (gtk.VBox):
         self.tracker_actions.set_sensitive(False)
 
     def add_tracker (self):
-        tracker_id = self.main_ui.gsd.create_tracker()
+        tracker_id = self._tracker_model.create_tracker()
         pixbuf = self._pixbuf_transform_color(
             STOCK_PIXBUFS['tracks'],
-            self.main_ui.gsd.get_tracker_color(tracker_id),
+            self._tracker_model.get_tracker_color(tracker_id),
             )
         # select our new tracker
         self.tracker_tree.get_selection().select_iter(
@@ -132,7 +133,7 @@ class TrackerBox (gtk.VBox):
         for row in self.tracker_model:
             tid = row[0]
             if tid != -1: # -1 == no tracker
-                self.main_ui.gsd.toggle_tracker(tid, tid == selected_tracker_id)
+                self._tracker_model.toggle_tracker(tid, tid == selected_tracker_id)
         self.tracker_actions.set_sensitive(selected_tracker_id != -1)
 
     def _clear_cb (self, action):
@@ -149,15 +150,89 @@ class TrackerBox (gtk.VBox):
         self._tracker_keep_tracks(selected_tracker_id)
 
     def _tracker_delete_tracks (self, tracker_id):
-        clearer = Undo.UndoableObject(
-            lambda *args: self.main_ui.cleared.append(self.main_ui.gsd.delete_by_tracker(tracker_id)),
-            lambda *args: [self.main_ui.gsd.add_value(*entry) for entry in self.main_ui.cleared.pop()],
-            self.main_ui.history)
-        clearer.perform()
+        self._tracker_model.delete_by_tracker(tracker_id)
 
     def _tracker_keep_tracks (self, tracker_id):
-        clearer = Undo.UndoableObject(
-            lambda *args: self.main_ui.cleared.append(self.main_ui.gsd.delete_except_for_tracker(tracker_id)),
-            lambda *args: [self.main_ui.gsd.add_value(*entry) for entry in self.main_ui.cleared.pop()],
-            self.main_ui.history)
-        clearer.perform()
+        self._tracker_model.delete_except_for_tracker(tracker_id)
+
+
+class TrackerModel:
+    """The 'model' that really perform the change on the SudokuView, e.g. set
+    the color"""
+
+    TRACKER_COLORS = [
+        # Use tango colors recommended here:
+        # http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
+        tuple([x / 255.0 for x in cols]) for cols in
+        [(32, 74, 135), # Sky Blue 3
+         (78, 154, 6), # Chameleon 3
+         (206, 92, 0), # Orange 3
+         (143, 89, 2), # Chocolate 3
+         (92, 53, 102), # Plum 3
+         (85, 87, 83), # Aluminium 5
+         (196, 160, 0), # Butter 3
+         ]
+        ]
+
+    def __init__(self, sudoku_view):
+        self._sudoku_view = sudoku_view
+        self._trackers = {}
+        self.__trackers_tracking__ = {}
+
+        sudoku_view.connect("view-updated", self._view_updated_cb)
+
+    def _view_updated_cb(self, view, x, y, value):
+        if not self._has_active_trackers():
+            return
+        for tracker_id, is_active in self.__trackers_tracking__.items():
+            if is_active:
+                self._add_to_tracker(tracker_id, x, y)
+
+    def _add_to_tracker(self, tracker_id, x, y):
+        color = self.get_tracker_color(tracker_id)
+        self._sudoku_view.set_color(x, y, color)
+        self._trackers[tracker_id].append((x, y))
+
+    def _has_active_trackers(self):
+        return True in self.__trackers_tracking__.values()
+
+    def create_tracker(self, identifier=0):
+        if not identifier:
+            identifier = 0
+        while self._trackers.has_key(identifier):
+            identifier += 1
+        self._trackers[identifier] = []
+        return identifier
+
+    def get_tracker_color(self, identifier):
+        return self.TRACKER_COLORS[identifier]
+        if 0:
+            new_color = self._generate_new_color()
+            self.TRACKER_COLORS.append(new_color)
+            return self.get_tracker_color(identifier)
+
+    def _generate_new_color(self):
+        random_color = self.TRACKER_COLORS[0]
+        while random_color in self.TRACKER_COLORS:
+            # If we have generated all possible colors, this will
+            # enter an infinite loop
+            random_color = (random.randint(0, 100)/100.0,
+                            random.randint(0, 100)/100.0,
+                            random.randint(0, 100)/100.0)
+        return random_color
+
+    def toggle_tracker(self, identifier, value):
+        """Toggle tracking for tracker identified by identifier."""
+        self.__trackers_tracking__[identifier] = value
+
+    def delete_by_tracker(self, identifier):
+        """Delete all cells tracked by tracker ID identifer."""
+        # copy the list, or there will be infinite-loop
+        entries = self._trackers[identifier][:]
+        for (x, y) in entries:
+            self._sudoku_view.update_model(x, y, 0)
+
+    def delete_except_for_tracker(self, identifier):
+        for tracker_id in self._trackers:
+            if not identifier == tracker_id:
+                self.delete_by_tracker(tracker_id)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]