[gnome-games/sudoku-tube] Make notes working
- From: Zhang Sen <zhangsen src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-games/sudoku-tube] Make notes working
- Date: Mon, 13 Jul 2009 05:32:17 +0000 (UTC)
commit 237d8f50f5d9b05a2500bfd5efa4cf1dbfbf1dc5
Author: Zhang Sen <zh jesse gmail com>
Date: Mon Jul 13 12:49:24 2009 +0800
Make notes working
* Use another class, NotesModel, to track notes. SudokuModel knows nothing
about notes.
gnome-sudoku/src/lib/gsudoku.py | 152 +++++++++++++++++++++++---------------
gnome-sudoku/src/lib/main.py | 10 +--
2 files changed, 96 insertions(+), 66 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/gsudoku.py b/gnome-sudoku/src/lib/gsudoku.py
index f50c428..2077be2 100644
--- a/gnome-sudoku/src/lib/gsudoku.py
+++ b/gnome-sudoku/src/lib/gsudoku.py
@@ -162,6 +162,7 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
self._model = None
self._do_highlight_cells = False
+ self._notes_model = None
for e in self.__entries__.values():
e.show()
@@ -182,6 +183,10 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
self.set_readonly_appearance(x, y, True)
self.set_value(x, y, val)
+ def connect_to_notes_model(self, model):
+ self._notes_model = model
+ self._notes_model.add_observer(self)
+
def update(self, values):
"""Update the GUI, called by a Model
@@ -212,7 +217,7 @@ class SudokuView(SudokuNumberGrid, gobject.GObject):
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)
+ self._notes_model.set_notes(widget.x, widget.y, top_note, bottom_note)
def _focus_callback(self, widget, event):
if self._do_highlight_cells:
@@ -308,11 +313,86 @@ class NumberBoxModel:
self.conflict = conflict
+class NotesModel:
+ """Track notes for a SudokuModel
+
+ Act as a observer of SudokuModel, and a model/observable for SudokuView.
+ SudokuModel should know nothing about notes.
+ """
+
+ def __init__(self, sudoku_model, group_size):
+ self._notes = {}
+ self._observers = []
+ self._group_size = group_size
+ self._model = sudoku_model
+ self._model.add_observer(self)
+
+ self._always_show_hints = False
+
+ def toggle_auto_hint(self, flag):
+ if flag:
+ self._always_show_hints = True
+ self.update_all_hints()
+ else:
+ self._always_show_hints = False
+ self.clear_hints()
+
+ def add_observer(self, observer):
+ self._observers.append(observer)
+
+ def _signal_observers(self, changes):
+ for observer in self._observers:
+ observer.update(changes)
+
+ def set_notes(self, x, y, top_note=None, bottom_note=None):
+ if (x, y) not in self._notes:
+ self._notes[(x, y)] = [None, None]
+
+ if top_note is not None:
+ self._notes[(x, y)][0] = top_note
+ if bottom_note is not None:
+ self._notes[(x, y)][0] = bottom_note
+
+ change = NumberBoxModel(x, y,
+ top_note=top_note, bottom_note=bottom_note)
+ self._signal_observers([change])
+
+ def update(self, changes):
+ if not self._always_show_hints:
+ return
+
+ self.update_all_hints()
+
+ def update_all_hints(self):
+ for x in range(self._group_size):
+ for y in range(self._group_size):
+ self._update_hint_for_entry(x, y)
+
+ def _update_hint_for_entry(self, x, y):
+ # no need to show anything if it's already filled, being correct or not
+ if self._model.get_value(x, y):
+ self.set_notes(x, y, bottom_note="")
+ return
+
+ vals = self._model.grid.possible_values(x, y)
+ vals = list(vals)
+ vals.sort()
+ if vals:
+ txt = ''.join([str(v) for v in vals])
+ self.set_notes(x, y, bottom_note=txt)
+ else:
+ self.set_notes(x, y, bottom_note="X")
+
+ def clear_hints(self):
+ for x in range(self.group_size):
+ for y in range(self.group_size):
+ self.set_notes(x, y, bottom_note="")
+
+
class SudokuModel:
def __init__ (self, grid, group_size):
self.hints = 0
- self.always_show_hints = False
self.auto_fills = 0
self.show_impossible_implications = False
self.impossible_hints = 0
@@ -341,27 +421,6 @@ class SudokuModel:
else:
self._show_hint_for_entry(entry, interactive = True)
- def _show_hint_for_entry(self, entry, interactive = False):
- if interactive:
- set_method = entry.set_note_text_interactive
- else:
- set_method = entry.set_note_text
- vals = self.grid.possible_values(entry.x, entry.y)
- vals = list(vals)
- vals.sort()
- if vals:
- ''.join([str(v) for v in vals])
- txt = ''.join([str(v) for v in vals])
- if txt != entry.get_text():
- set_method(bottom_text = txt)
- self.hints += 1
- elif not entry.get_text():
- if entry.get_text() != 'X':
- self.hints += 1
- set_method(bottom_text = 'X')
- else:
- set_method(bottom_text = "")
-
def reset_grid (self):
"""Reset grid to its original setup.
@@ -377,22 +436,6 @@ class SudokuModel:
self.remove(x, y, do_removal = True)
return removed
- def clear_notes (self, clear_args = {'top_text':'', 'bottom_text':''}):
- """Remove all notes."""
- self.removed = []
- for x in range(self.group_size):
- for y in range(self.group_size):
- e = self.__entries__[(x, y)]
- top, bottom = e.get_note_text()
- if top or bottom:
- self.removed.append((x, y, (top, bottom)))
- e.set_note_text(**clear_args)
- e.queue_draw()
- return self.removed
-
- def clear_hints (self):
- self.clear_notes(clear_args = {'bottom_text':''})
-
def _blank_grid(self):
for x in range(self.group_size):
for y in range(self.group_size):
@@ -448,23 +491,6 @@ class SudokuModel:
if self.always_show_hints:
self.update_all_hints()
- def update_all_hints (self):
- for x in range(self.group_size):
- for y in range(self.group_size):
- e = self.__entries__[(x, y)]
- if e.read_only:
- pass
- elif e.get_text():
- e.set_note_text(bottom_text = '')
- else:
- self._show_hint_for_entry(e)
-
- def _entry_validate(self, widget, *args):
- val = widget.get_value()
- self.add_value(widget.x, widget.y, val)
- if self.grid.check_for_completeness():
- self.emit('puzzle-finished')
-
def set_value(self, x, y, value):
result = []
# first remove conflicts; grid.add should return conflicts together
@@ -475,10 +501,13 @@ class SudokuModel:
change = NumberBoxModel(x=entry[0], y=entry[1], conflict=False)
result.append(change)
- try:
- self.grid.add(x, y, value) # force=True???
- except sudoku.ConflictError, err:
- new_conflicts = self.grid.find_conflicts(x, y, value)
+ if not value: # should use unified way to update the grid
+ self.grid.remove(x, y)
+ else:
+ try:
+ self.grid.add(x, y, value) # force=True???
+ except sudoku.ConflictError, err:
+ new_conflicts = self.grid.find_conflicts(x, y, value)
has_conflict = True if new_conflicts else False
result.append(NumberBoxModel(x, y, value, conflict=has_conflict))
if new_conflicts:
@@ -491,6 +520,9 @@ class SudokuModel:
if self.grid.check_for_completeness():
self._signal_completeness()
+ def get_value(self, x, y):
+ return self.grid._get_(x, y)
+
def set_notes(self, x, y, top_note, bottom_note):
# should first add notes to model
change = NumberBoxModel(x, y,
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index 99d721d..d522e77 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -119,7 +119,10 @@ class UI (gconf_wrapper.GConfWrapper):
self._puzzle = puzzle
if game_type == game_selector.NewOrSavedGameSelector.NEW_GAME:
self._main_model = gsudoku.SudokuModel(puzzle, 9)
+ self._notes_model = gsudoku.NotesModel(self._main_model, group_size=9)
+
self._main_grid_vew.connect_to_model(self._main_model)
+ self._main_grid_vew.connect_to_notes_model(self._notes_model)
elif game_type == game_selector.NewOrSavedGameSelector.SAVED_GAME:
saver.open_game(self, puzzle)
self._post_open_setup()
@@ -479,12 +482,7 @@ class UI (gconf_wrapper.GConfWrapper):
self.gsd.show_hint()
def auto_hint_cb (self, action):
- if action.get_active():
- self.gsd.always_show_hints = True
- self.gsd.update_all_hints()
- else:
- self.gsd.always_show_hints = False
- self.gsd.clear_hints()
+ self._notes_model.toggle_auto_hint(action.get_active())
def impossible_implication_cb (self, action):
if action.get_active():
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]