[gnome-games/sudoku-tube] Let SudokuView directly access tracker stuff



commit f0075eea3d39dcf271dd5c1f4f682f793cb288e5
Author: Zhang Sen <zh jesse gmail com>
Date:   Fri Jul 24 07:47:27 2009 +0800

    Let SudokuView directly access tracker stuff

 gnome-sudoku/src/lib/main.py        |   10 ++--
 gnome-sudoku/src/lib/number_box.py  |    6 --
 gnome-sudoku/src/lib/tracker_box.py |  104 ++--------------------------
 gnome-sudoku/src/lib/view.py        |  134 ++++++++++++++++++++++++++++++++---
 4 files changed, 133 insertions(+), 121 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index 54d1b16..2a3101c 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -233,9 +233,9 @@ 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 = tracker_box.Tracker(self._main_grid_vew)
-        self._tracker.hide()
-        tracker_ui_container.pack_start(self._tracker.get_view())
+        self._tracker_ui = tracker_box.TrackerBox(self._main_grid_vew)
+        self._tracker_ui.hide()
+        tracker_ui_container.pack_start(self._tracker_ui)
 
         self._setup_side_view()
         side_grid_container.add(self._side_grid_vew)
@@ -514,9 +514,9 @@ class UI (gconf_wrapper.GConfWrapper):
 
     def tracker_toggle_cb (self, widg):
         if widg.get_active():
-            self._tracker.show()
+            self._tracker_ui.show()
         else:
-            self._tracker.hide()
+            self._tracker_ui.hide()
 
     def toggle_toolbar_cb (self, widg):
         if widg.get_active():
diff --git a/gnome-sudoku/src/lib/number_box.py b/gnome-sudoku/src/lib/number_box.py
index fabcb11..7d9ad81 100644
--- a/gnome-sudoku/src/lib/number_box.py
+++ b/gnome-sudoku/src/lib/number_box.py
@@ -531,12 +531,6 @@ class SudokuNumberBox (_NumberBox):
     def unset_color (self):
         self.set_color(None)
 
-    def set_error_highlight (self, val):
-        if val:
-            self.set_text_color((1.0, 0, 0))
-        else:
-            self.set_text_color(self.normal_color)
-
     def set_read_only (self, val):
         self.read_only = val
         if not hasattr(self, 'bold_font'):
diff --git a/gnome-sudoku/src/lib/tracker_box.py b/gnome-sudoku/src/lib/tracker_box.py
index 8f512ff..882064d 100644
--- a/gnome-sudoku/src/lib/tracker_box.py
+++ b/gnome-sudoku/src/lib/tracker_box.py
@@ -31,38 +31,6 @@ def _add_tracker_stock_icon():
 
 _add_tracker_stock_icon()
 
-TRACKER_COLORS = [
-    # Use tango colors recommended here:
-    # http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
-    tuple([c / 255.0 for c 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 _get_tracker_color(identifier):
-    try:
-        return TRACKER_COLORS[identifier]
-    except IndexError:
-        new_color = _generate_new_color()
-        TRACKER_COLORS.append(new_color)
-        return _get_tracker_color(identifier)
-
-def _generate_new_color():
-    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)
-    return random_color
-
 def _pixbuf_transform_color(pixbuf, color):
     """Return new pixbuf with color changed to color"""
     pixbuf_str = pixbuf.get_pixels()
@@ -79,13 +47,13 @@ def _pixbuf_transform_color(pixbuf, color):
             pixbuf.get_rowstride())
 
 
-class _TrackerBox (gtk.VBox):
+class TrackerBox(gtk.VBox):
 
-    def __init__(self, controller):
+    def __init__(self, sudoku_view):
         gtk.VBox.__init__(self)
         self.builder = gtk.Builder()
         self.builder.add_from_file(os.path.join(defaults.UI_DIR, 'tracker.ui'))
-        self._view_controller = controller
+        self._view_controller = sudoku_view.get_tracker_controller()
         vbox = self.builder.get_object('vbox1')
         vbox.unparent()
         self.pack_start(vbox, expand = True, fill = True)
@@ -143,9 +111,8 @@ class _TrackerBox (gtk.VBox):
 
     def add_tracker (self):
         tracker_id = self._view_controller.create_tracker()
-        pixbuf = _pixbuf_transform_color(
-            STOCK_PIXBUFS['tracks'],
-            _get_tracker_color(tracker_id))
+        color = self._view_controller.get_tracker_color(tracker_id)
+        pixbuf = _pixbuf_transform_color(STOCK_PIXBUFS['tracks'], color)
         # select our new tracker
         self.tracker_tree.get_selection().select_iter(
             self.tracker_model.append([tracker_id,
@@ -186,64 +153,3 @@ class _TrackerBox (gtk.VBox):
         mod, itr = self.tracker_tree.get_selection().get_selected()
         selected_tracker_id = mod.get_value(itr, 0)
         self._view_controller.delete_except_for_tracker(selected_tracker_id)
-
-
-class Tracker:
-    """The controller that really perform the changes on the SudokuView, e.g.
-    set the color"""
-
-    def __init__(self, sudoku_view):
-        self._sudoku_view = sudoku_view
-        self._trackers = {}
-        self.__trackers_tracking__ = {}
-        self._tracker_box_view = _TrackerBox(self)
-
-        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 = _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 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)
-
-    def get_view(self):
-        return self._tracker_box_view
-
-    def hide(self):
-        self._tracker_box_view.hide()
-
-    def show(self):
-        self._tracker_box_view.show_all()
diff --git a/gnome-sudoku/src/lib/view.py b/gnome-sudoku/src/lib/view.py
index 2b799ca..8e32715 100644
--- a/gnome-sudoku/src/lib/view.py
+++ b/gnome-sudoku/src/lib/view.py
@@ -8,6 +8,92 @@ import gobject
 import colors
 import number_box
 
+
+TRACKER_COLORS = [
+    # Use tango colors recommended here:
+    # http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
+    tuple([c / 255.0 for c 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 _generate_new_color():
+    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)
+    return random_color
+
+
+class _Tracker:
+    def __init__(self, sudoku_view):
+        self._trackers = {} # id => [coords]
+        self.__trackers_tracking__ = {} # id => True/False
+        self._tracker_by_coords = {} # coords => id
+        self._sudoku_view = sudoku_view
+
+    def add_to_tracker(self, tracker_id, x, y):
+        self._trackers[tracker_id].append((x, y))
+        self._tracker_by_coords[(x, y)] = tracker_id
+
+    def remove_from_tracker(self, tracker_id, x, y):
+        # TODO how to remove from self._trackers?
+        self._tracker_by_coords[(x, y)] = None
+
+    def get_active_tracker(self):
+        for tracker_id in self.__trackers_tracking__:
+            if self.__trackers_tracking__[tracker_id]:
+                return tracker_id
+        return None
+
+    def get_tracker_by_coord(self, x, y):
+        if (x, y) in self._tracker_by_coords:
+            return self._tracker_by_coords[(x, y)]
+        else:
+            return None
+
+    def create_tracker(self):
+        identifier = 0
+        while identifier in self._trackers:
+            identifier += 1
+        self._trackers[identifier] = []
+        return identifier
+
+    def toggle_tracker(self, identifier, flag):
+        self.__trackers_tracking__[identifier] = flag
+
+    def delete_by_tracker(self, identifier):
+        """Delete all cells tracked by tracker ID identifier."""
+        # copy the list, or there will be infinite-loop
+        entries = self._trackers[identifier]
+        self._trackers[identifier] = []
+        for (x, y) in entries:
+            self._tracker_by_coords[(x, y)] = None
+            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)
+
+    def get_tracker_color(self, identifier):
+        try:
+            return TRACKER_COLORS[identifier]
+        except IndexError:
+            new_color = _generate_new_color()
+            TRACKER_COLORS.append(new_color)
+            return self.get_tracker_color(identifier)
+
+
 def gtkcolor_to_rgb (color):
     return (color.red   / float(2**16),
             color.green / float(2**16),
@@ -85,6 +171,10 @@ class SudokuNumberGrid (gtk.AspectFrame):
             e.modify_bg(gtk.STATE_NORMAL, color)
 
     def set_value(self, x, y, value):
+        if not value:
+            tid = self._tracker.get_tracker_by_coord(x, y)
+            if tid is not None:
+                self._tracker.remove_from_tracker(tid, x, y)
         self.__entries__[(x, y)].set_value(value)
 
     def set_readonly_appearance(self, x, y, flag):
@@ -108,10 +198,8 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
     # some signals to give notice about change of the View
     __gsignals__ = {
             # 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))}
+            "puzzle-finished": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
+            }
 
     def __init__(self, group_size):
         SudokuNumberGrid.__init__(self, group_size)
@@ -128,6 +216,8 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
             e.connect('focus-in-event', self._focus_callback)
             e.connect('key-press-event', self._key_press_cb)
 
+        self._tracker = _Tracker(self)
+
     def connect_to_model(self, model):
         if not model:
             return
@@ -151,18 +241,37 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
         values should be a list of NumberBoxModel"""
         for box in values:
             x, y, value, conflict = box.x, box.y, box.value, box.conflict
-            if value is not None:
+            is_new_value = value is not None
+            if is_new_value:
                 self.set_value(x, y, value)
-                self.emit("view-updated", x, y, value)
-            if conflict is not None:
-                self._show_conflict(x, y, conflict)
+            self.set_color(x, y,
+                    self._refresh_color(x, y, conflict, is_new_value))
+
+    def _refresh_color(self, x, y, conflict, is_new_value):
+        """Set the color according to several rules, conflict/tracker, etc
+        """
+        # conflict
+        if conflict:
+            return (1.0, 0, 0)
+
+        # there is active tracker
+        tid = self._tracker.get_active_tracker()
+        if tid is not None and is_new_value: # old values won't go into tracker
+            self._tracker.add_to_tracker(tid, x, y)
+            return self._tracker.get_tracker_color(tid)
+
+        # the entry was in a tracker; should resume it if its color has been
+        # overridden by conflict
+        tid = self._tracker.get_tracker_by_coord(x, y)
+        if tid is not None:
+            return self._tracker.get_tracker_color(tid)
+
+        # default black color
+        return None
 
     def puzzle_finished_cb(self):
         self.emit("puzzle-finished")
 
-    def _show_conflict(self, x, y, flag):
-        self.__entries__[(x, y)].set_error_highlight(flag)
-
     def update_notes(self, notes_list):
         for notes in notes_list:
             x, y, top_note, bottom_note = notes
@@ -258,3 +367,6 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
             return opposite_edge[x], y
         else:
             return None, None
+
+    def get_tracker_controller(self):
+        return self._tracker



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