[gnome-games/sudoku-tube] Move the SudokuView class out
- From: Zhang Sen <zhangsen src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-games/sudoku-tube] Move the SudokuView class out
- Date: Wed, 22 Jul 2009 12:07:01 +0000 (UTC)
commit b7e46eedbc0a03af2f5cdd024af099d2efd73a3b
Author: Zhang Sen <zh jesse gmail com>
Date: Wed Jul 22 18:52:49 2009 +0800
Move the SudokuView class out
gnome-sudoku/src/lib/dancer.py | 7 +-
gnome-sudoku/src/lib/gsudoku.py | 589 --------------------------------------
gnome-sudoku/src/lib/main.py | 15 +-
gnome-sudoku/src/lib/model.py | 331 +++++++++++++++++++++
gnome-sudoku/src/lib/printing.py | 4 +-
gnome-sudoku/src/lib/view.py | 260 +++++++++++++++++
6 files changed, 605 insertions(+), 601 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/dancer.py b/gnome-sudoku/src/lib/dancer.py
index 980c57b..8400694 100644
--- a/gnome-sudoku/src/lib/dancer.py
+++ b/gnome-sudoku/src/lib/dancer.py
@@ -101,7 +101,8 @@ class GridDancer:
if __name__ == '__main__':
def test_dance_grid ():
- import gsudoku
+ import model
+ import view
window = gtk.Window()
game = '''9 1 6 3 2 8 4 5 7
5 7 4 6 1 9 2 8 3
@@ -112,8 +113,8 @@ if __name__ == '__main__':
4 6 9 1 8 7 5 3 2
1 2 8 9 5 3 6 7 4
7 5 3 4 6 2 8 1 9'''
- view = gsudoku.SudokuView(9)
- model = gsudoku.SudokuModel(game, 9)
+ view = view.SudokuView(9)
+ model = model.SudokuModel(game, 9)
view.connect_to_model(model)
dancer = GridDancer(view, model)
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index a25788f..6ba8ca4 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -15,7 +15,8 @@ from gettext import gettext as _
from gettext import ngettext
import game_selector
-import gsudoku
+import model
+import view
import printing
import saver
import sudoku_generator_gui
@@ -118,8 +119,8 @@ class UI (gconf_wrapper.GConfWrapper):
"""Finally enter the puzzle"""
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_model = model.SudokuModel(puzzle, 9)
+ self._notes_model = model.NotesModel(self._main_model, group_size=9)
elif game_type == game_selector.NewOrSavedGameSelector.SAVED_GAME:
self._open_saved_game(puzzle)
else:
@@ -130,10 +131,10 @@ class UI (gconf_wrapper.GConfWrapper):
def _open_saved_game(self, jar):
virgin, in_prog = jar["game"].split('\n')
- self._main_model = gsudoku.SudokuModel(virgin, 9, in_prog)
+ self._main_model = model.SudokuModel(virgin, 9, in_prog)
self._main_model.set_autofill_count(jar["gsd.auto_fills"])
- self._notes_model = gsudoku.NotesModel(self._main_model, group_size=9)
+ self._notes_model = model.NotesModel(self._main_model, group_size=9)
self._notes_model.set_hints_count(jar["gsd.hints"])
for (x, y, top, bottom) in jar["notes"]:
self._notes_model.set_notes(x, y, top, bottom)
@@ -228,7 +229,7 @@ class UI (gconf_wrapper.GConfWrapper):
side_grid_container = self.builder.get_object("side_grid_container")
tracker_ui_container = self.builder.get_object("tracker_ui_container")
- self._main_grid_vew = gsudoku.SudokuView(group_size=9)
+ self._main_grid_vew = view.SudokuView(group_size=9)
self._main_grid_vew.connect('puzzle-finished', self.you_win_callback)
main_grid_container.pack_start(self._main_grid_vew, padding=6)
@@ -240,7 +241,7 @@ class UI (gconf_wrapper.GConfWrapper):
side_grid_container.add(self._side_grid_vew)
def _setup_side_view(self):
- self._side_grid_vew = gsudoku.SudokuView(group_size=9)
+ self._side_grid_vew = view.SudokuView(group_size=9)
for x in range(9):
for y in range(9):
self._side_grid_vew.set_readonly_appearance(x, y, True)
diff --git a/gnome-sudoku/src/lib/model.py b/gnome-sudoku/src/lib/model.py
new file mode 100644
index 0000000..598e2b0
--- /dev/null
+++ b/gnome-sudoku/src/lib/model.py
@@ -0,0 +1,331 @@
+# -*- coding: utf-8 -*-
+import sudoku
+
+
+class ParallelDict (dict):
+ """A handy new sort of dictionary for tracking conflicts.
+
+ pd = ParallelDict()
+ pd[1] = [2, 3, 4] # 1 is linked with 2, 3 and 4
+ pd -> {1:[2, 3, 4], 2:[1], 3:[1], 4:[1]}
+ pd[2] = [1, 3, 4] # 2 is linked with 3 and 4 as well as 1
+ pd -> {1: [2, 3, 4], 2:[3, 4], 3:[1, 2], 4:[1, 2]}
+ Now for the cool part...
+ del pd[1]
+ pd -> {2: [2, 3], 3:[2], 4:[2]}
+
+ Pretty neat, no?
+ """
+ def __init__ (self, *args):
+ dict.__init__(self, *args)
+
+ def __setitem__ (self, k, v):
+ dict.__setitem__(self, k, set(v))
+ for i in v:
+ if i == k:
+ continue
+ if self.has_key(i):
+ self[i].add(k)
+ else:
+ dict.__setitem__(self, i, set([k]))
+
+ def __delitem__ (self, k):
+ v = self[k]
+ dict.__delitem__(self, k)
+ for i in v:
+ if i == k:
+ continue
+ if self.has_key(i):
+ # Make sure we have a reference to i. If we don't
+ # something has gone wrong... but according to bug
+ # 385937 this has gone wrong at least once, so we'd
+ # better check for it.
+ if k in self[i]:
+ self[i].remove(k)
+ if not self[i]:
+ # If k was the last value in the list of values
+ # for i, then we delete i from our dictionary
+ dict.__delitem__(self, i)
+
+
+class NumberBoxModel:
+ def __init__(self, x, y, value=None, conflict=None):
+ self.x = x
+ self.y = y
+ self.value = value
+ 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
+ self._hints_count = 0
+
+ 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)
+ init_change = []
+ for (x, y) in self._notes:
+ top, bottom = self._notes[(x, y)]
+ init_change.append((x, y, top, bottom))
+ self._signal_observers(init_change)
+
+ def _signal_observers(self, changes):
+ for observer in self._observers:
+ observer.update_notes(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)][1] = bottom_note
+
+ change = (x, y, top_note, bottom_note)
+ self._signal_observers([change])
+
+ def update(self, changes):
+ if not self._always_show_hints:
+ return
+
+ self.update_all_hints()
+
+ def puzzle_finished_cb(self):
+ self._clear_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 show_hint(self, x, y):
+ 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)
+ self._increase_hints_count()
+ else:
+ self.set_notes(x, y, bottom_note="X")
+
+ def _clear_hints(self):
+ self._clear_bottom_note()
+
+ def _clear_top_note(self):
+ for x in range(self._group_size):
+ for y in range(self._group_size):
+ self.set_notes(x, y, top_note="")
+
+ def _clear_bottom_note(self):
+ for x in range(self._group_size):
+ for y in range(self._group_size):
+ self.set_notes(x, y, bottom_note="")
+
+ def _increase_hints_count(self):
+ self._hints_count += 1
+
+ def set_hints_count(self, count):
+ self._hints_count = count
+
+ def get_hints_count(self):
+ return self._hints_count
+
+ def clear_notes(self):
+ self._clear_top_note()
+ self._clear_bottom_note()
+
+class SudokuModel:
+
+ def __init__ (self, virgin_grid, group_size, initial_grid=None):
+ self.autofill_count = 0
+ self.show_impossible_implications = False
+ self.impossible_hints = 0
+ self.impossibilities = []
+ self.__trackers_tracking__ = {}
+ self.group_size = group_size
+ self.grid = None
+ self._virgin_grid = None
+ self._observers = []
+
+ self.__error_pairs__ = ParallelDict()
+ self._setup_virgin_grid(virgin_grid)
+ if initial_grid:
+ self._setup_initial_grid(initial_grid)
+
+ def add_observer(self, observer):
+ self._observers.append(observer)
+
+ def _signal_observers(self, values):
+ for observer in self._observers:
+ observer.update(values)
+
+ def _signal_completeness(self):
+ for observer in self._observers:
+ observer.puzzle_finished_cb()
+
+ def reset_grid (self):
+ """Reset grid to its original setup.
+ """
+
+ for x in range(self.group_size):
+ for y in range(self.group_size):
+ if not self.grid.virgin._get_(x, y):
+ # conflicting values are not being tracked, so we have to
+ # set_value on all the entries, instead of only filled ones
+ self.set_value(x, y, 0)
+
+ def _setup_virgin_grid(self, virgin):
+ """both grid and initial_grid should be str"""
+ self._virgin_grid = [int(c) for c in virgin.split()]
+ self.grid = sudoku.InteractiveSudoku(virgin, group_size=self.group_size)
+
+ def _setup_initial_grid(self, initial_grid):
+ values = [int(c) for c in initial_grid.split()]
+ for row in range(self.group_size):
+ for col in range(self.group_size):
+ index = row * 9 + col
+ if values[index] and not self.grid._get_(col, row):
+ self.set_value(col, row, values[index])
+
+ def set_value(self, x, y, value):
+ result = []
+ old_conflicts = self._remove_old_conficts(x, y)
+ new_conflicts = []
+
+ # Some value won't go into the grid, e.g. conflicts values?
+ # This makes things complicated.
+ if not value:
+ if self.grid._get_(x, y):
+ self.grid.remove(x, y)
+ else:
+ try:
+ self.grid.add(x, y, value, force=True)
+ except sudoku.ConflictError, err:
+ new_conflicts = self._find_new_conflicts(x, y, value)
+
+ flag = True if new_conflicts else False
+ result.append((x, y, value, flag))
+ result.extend(old_conflicts)
+ result.extend(new_conflicts)
+
+ self._signal_observers(result)
+ self._check_for_completeness()
+
+ def get_value(self, x, y):
+ return self.grid._get_(x, y)
+
+ def get_virgin_value(self, x, y):
+ return self._virgin_grid[9 * y + x]
+
+ def _remove_old_conficts(self, x, y):
+ result = []
+ old_conflicts = self._remove_related_conflicts(x, y)
+ for entry in old_conflicts:
+ change = (entry[0], entry[1], None, False)
+ result.append(change)
+ return result
+
+ def _find_new_conflicts(self, x, y, value):
+ result = []
+ new_conflicts = self.grid.find_conflicts(x, y, value)
+ if new_conflicts:
+ self.__error_pairs__[(x, y)] = new_conflicts
+ for entry in new_conflicts:
+ change = (entry[0], entry[1], None, True)
+ result.append(change)
+ return result
+
+ def _remove_related_conflicts(self, x, y):
+ result = []
+ if self.__error_pairs__.has_key((x, y)):
+ errors_removed = self.__error_pairs__[(x, y)]
+ del self.__error_pairs__[(x, y)]
+ for coord in errors_removed:
+ # If we're not an error by some other pairing...
+ if not self.__error_pairs__.has_key(coord):
+ result.append(coord)
+ return result
+
+ def _check_for_completeness(self):
+ if self.grid.check_for_completeness():
+ self._signal_completeness()
+
+ def set_autofill_count(self, count):
+ self.autofill_count = count
+
+ def get_autofill_count(self):
+ return self.autofill_count
+
+ def auto_fill (self):
+ self.autofill_count += 1
+ result = []
+
+ changed = set(self.grid.auto_fill()) # there are duplicate?
+ for coords, val in changed:
+ x, y = coords
+ result.append((x, y, val, None))
+
+ self._signal_observers(result)
+ self._check_for_completeness()
+
+ def auto_fill_current(self, x, y):
+ filled = self.grid.auto_fill_for_xy(x, y)
+ if filled and filled != -1:
+ self.set_value(x, y, filled[1])
+
+ def _mark_impossible_implications(self, x, y):
+ if not self.grid:
+ return
+ implications = self.grid.find_impossible_implications(x, y)
+ if implications:
+ for x, y in implications:
+ self.__entries__[(x, y)].set_impossible(True)
+ if not (x, y) in self.impossibilities:
+ self.impossible_hints += 1
+ for x, y in self.impossibilities:
+ if not (x, y) in implications:
+ self.__entries__[(x, y)].set_impossible(False)
+ self.impossibilities = implications
+
+ def _trackers_for_point(self, x, y, val = None):
+ if val:
+ # if we have a value we can do this a simpler way...
+ track_for_point = filter(
+ lambda t: (x, y, val) in t[1],
+ self.trackers.items()
+ )
+ else:
+ track_for_point = filter(
+ lambda tkr: True in [t[0] == x and t[1] == y for t in tkr[1]],
+ self.trackers.items())
+ return [t[0] for t in track_for_point]
diff --git a/gnome-sudoku/src/lib/printing.py b/gnome-sudoku/src/lib/printing.py
index 85fab43..bcbcc2c 100644
--- a/gnome-sudoku/src/lib/printing.py
+++ b/gnome-sudoku/src/lib/printing.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import gtk, cairo, time
import os.path
-import sudoku, gsudoku, saver, defaults
+import sudoku, model, saver, defaults
from gtk_goodies import gconf_wrapper
def fit_squares_in_rectangle (width, height, n, margin = 0):
@@ -85,7 +85,7 @@ class SudokuPrinter:
cr.move_to(left, top - height / 2)
cr.show_text(label)
- if isinstance(sudoku, gsudoku.SudokuModel):
+ if isinstance(sudoku, model.SudokuModel):
sudoku = sudoku.grid
sudoku_thumber.draw_sudoku (cr, sudoku.grid, None, best_square_size, left, top)
diff --git a/gnome-sudoku/src/lib/view.py b/gnome-sudoku/src/lib/view.py
new file mode 100644
index 0000000..5b10373
--- /dev/null
+++ b/gnome-sudoku/src/lib/view.py
@@ -0,0 +1,260 @@
+# -*- coding: utf-8 -*-
+
+import math
+
+import gtk
+import gobject
+
+import colors
+import number_box
+
+def gtkcolor_to_rgb (color):
+ return (color.red / float(2**16),
+ color.green / float(2**16),
+ color.blue / float(2**16))
+
+SPACING_FACTOR = 40 # The size of a box compared (roughly) to the size
+ # of padding -- the larger this is, the smaller
+ # the spaces
+SMALL_TO_BIG_FACTOR = 3.5 # The number of times wider than a small line a big line is.
+
+class SudokuNumberGrid (gtk.AspectFrame):
+
+ def __init__ (self, group_size):
+ self.table = gtk.Table(rows = group_size, columns = group_size, homogeneous = True)
+ self.group_size = group_size
+ self.__entries__ = {}
+ self._setup_table()
+
+ gtk.AspectFrame.__init__(self, obey_child = False)
+ self.set_shadow_type(gtk.SHADOW_NONE)
+ self.eb = gtk.EventBox()
+ self.eb.add(self.table)
+ self.add(self.eb)
+ self.connect('size-allocate', self._allocate_cb)
+ self.show_all()
+
+ def _setup_table(self):
+ for x in range(self.group_size):
+ for y in range(self.group_size):
+ e = number_box.SudokuNumberBox(upper = self.group_size)
+ e.x = x
+ e.y = y
+ self.table.attach(e, x, x+1, y, y+1,
+ )
+ self.__entries__[(x, y)] = e
+
+ def _allocate_cb (self, widget, rect):
+ if rect.width > rect.height:
+ side = rect.height
+ else: side = rect.width
+ # we want our small spacing to be 1/15th the size of a box
+ spacing = float(side) / (self.group_size * SPACING_FACTOR)
+ if spacing == 0:
+ spacing = 1
+ if hasattr(self, 'small_spacing') and spacing == self.small_spacing:
+ return
+ else:
+ self._change_spacing(spacing)
+
+ def _change_spacing (self, small_spacing):
+ self.small_spacing = small_spacing
+ self.big_spacing = int(small_spacing*SMALL_TO_BIG_FACTOR)
+ self.table.set_row_spacings(int(small_spacing))
+ self.table.set_col_spacings(int(small_spacing))
+ box_side = int(math.sqrt(self.group_size))
+ for n in range(1, box_side):
+ self.table.set_row_spacing(box_side*n-1, self.big_spacing)
+ self.table.set_col_spacing(box_side*n-1, self.big_spacing)
+ self.table.set_border_width(self.big_spacing)
+
+ def set_bg_color (self, color):
+ if type(color) == str:
+ try:
+ color = gtk.gdk.color_parse(color)
+ except:
+ print 'set_bg_color handed Bad color', color
+ return
+ self.eb.modify_bg(gtk.STATE_NORMAL, color)
+ self.eb.modify_base(gtk.STATE_NORMAL, color)
+ self.eb.modify_fg(gtk.STATE_NORMAL, color)
+ self.table.modify_bg(gtk.STATE_NORMAL, color)
+ self.table.modify_base(gtk.STATE_NORMAL, color)
+ self.table.modify_fg(gtk.STATE_NORMAL, color)
+ for e in self.__entries__.values():
+ e.modify_bg(gtk.STATE_NORMAL, color)
+
+ def set_value(self, x, y, value):
+ self.__entries__[(x, y)].set_value(value)
+
+ 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_background_color(self, x, y, color):
+ self.__entries__[(x, y)].set_background_color(color)
+
+ def set_focus(self, x, y):
+ self.table.set_focus_child(self.__entries__[x, y])
+
+ def get_focus(self):
+ return self.table.get_focus_child()
+
+
+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))}
+
+ def __init__(self, group_size):
+ SudokuNumberGrid.__init__(self, group_size)
+ gobject.GObject.__init__(self)
+
+ self._model = None
+ self._do_highlight_cells = False
+ self._notes_model = None
+
+ for e in self.__entries__.values():
+ e.show()
+ e.connect('number-changed', self._number_changed_cb)
+ e.connect('notes-changed', self._notes_changed_cb)
+ e.connect('focus-in-event', self._focus_callback)
+ e.connect('key-press-event', self._key_press_cb)
+
+ def connect_to_model(self, model):
+ if not model:
+ return
+ self._model = model
+ model.add_observer(self)
+ for x in range(self.group_size):
+ for y in range(self.group_size):
+ val = model.get_value(x, y)
+ if val:
+ self.set_value(x, y, val)
+ if model.get_virgin_value(x, y):
+ self.set_readonly_appearance(x, y, True)
+
+ 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
+
+ values should be a list of NumberBoxModel"""
+ for box in values:
+ x, y, value, conflict = box
+ if value is not None:
+ self.set_value(x, y, value)
+ self.emit("view-updated", x, y, value)
+ if conflict is not None:
+ self._show_conflict(x, y, conflict)
+
+ def puzzle_finished_cb(self):
+ self.emit("puzzle-finished")
+
+ def _show_conflict(self, x, y, conflict):
+ self.__entries__[(x, y)].set_error_highlight(conflict)
+
+ def update_notes(self, notes_list):
+ for notes in notes_list:
+ x, y, top_note, bottom_note = notes
+ self.__entries__[(x, y)].set_notes((top_note, bottom_note))
+
+ def _number_changed_cb(self, widget, 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._notes_model.set_notes(widget.x, widget.y, top_note, bottom_note)
+
+ def _focus_callback(self, widget, event):
+ if self._do_highlight_cells:
+ self._highlight_cells()
+
+ def _key_press_cb(self, widget, event):
+ key = gtk.gdk.keyval_name(event.keyval)
+ dest_x, dest_y = self._go_around(widget.x, widget.y, key)
+ if dest_x is not None:
+ self.set_focus(dest_x, dest_y)
+
+ def toggle_highlight (self, val):
+ self._do_highlight_cells = val
+ if val:
+ self._highlight_cells()
+ else:
+ self.unhighlight_cells()
+
+ def unhighlight_cells(self):
+ for e in self.__entries__.values():
+ e.set_background_color(None)
+
+ def _highlight_cells(self):
+ focused = self.get_focus()
+ if not focused: # no need to do anything if no box has focus
+ return
+ self.unhighlight_cells() # first clear all the cells
+ if not hasattr(self, 'box_color'):
+ self._get_highlight_colors()
+ my_x, my_y = focused.x, focused.y
+
+ grid = self._model.grid
+ for x, y in grid.col_coords[my_x]:
+ if (x, y) != (my_x, my_y):
+ self.__entries__[(x, y)].set_background_color(self.col_color)
+ for x, y in grid.row_coords[my_y]:
+ if (x, y) != (my_x, my_y):
+ self.__entries__[(x, y)].set_background_color(self.row_color)
+ for x, y in grid.box_coords[grid.box_by_coords[(my_x, my_y)]]:
+ if (x, y) != (my_x, my_y):
+ e = self.__entries__[(x, y)]
+ if x == my_x:
+ e.set_background_color(self.box_and_col_color)
+ elif y == my_y:
+ e.set_background_color(self.box_and_row_color)
+ else:
+ e.set_background_color(self.box_color)
+
+ def _get_highlight_colors(self):
+ entry = self.__entries__.values()[0]
+ default_color = gtkcolor_to_rgb(entry.style.bg[gtk.STATE_SELECTED])
+ hsv = colors.rgb_to_hsv(*default_color)
+ box_s = hsv[1]
+ box_v = hsv[2]
+ if box_v < 0.5:
+ box_v = box_v * 2
+ if box_s > 0.75:
+ box_s = box_s * 0.5
+ else:
+ box_s = box_s * 1.5
+ if box_s > 1:
+ box_s = 1.0
+ self.box_color = colors.hsv_to_rgb(hsv[0], box_s, box_v)
+ self.box_and_row_color = colors.rotate_hue_rgb(*self.box_color, **{'rotate_by': 0.33 / 2})
+ self.row_color = colors.rotate_hue_rgb(*self.box_color, **{'rotate_by': 0.33})
+ self.col_color = colors.rotate_hue_rgb(*self.box_color, **{'rotate_by': 0.66})
+ self.box_and_col_color = colors.rotate_hue_rgb(*self.box_color, **{'rotate_by': 1.0 - (0.33 / 2)})
+
+ def _go_around(self, x, y, direction):
+ '''return the coordinate if we should go to the other side of the grid.
+ Or else return None.'''
+ limit_min, limit_max = 0, self.group_size - 1
+ y_edge = [(limit_min, 'Up'), (limit_max, 'Down')]
+ x_edge = [(limit_min, 'Left'), (limit_max, 'Right')]
+ opposite_edge = {limit_min: limit_max, limit_max: limit_min}
+
+ if (y, direction) in y_edge:
+ return x, opposite_edge[y]
+ elif (x, direction) in x_edge:
+ return opposite_edge[x], y
+ else:
+ return None, None
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]