117 lines
3.3 KiB
Python
117 lines
3.3 KiB
Python
#--------------------------------------------------------------------------
|
|
#
|
|
# PyGUI - Grid View - Generic
|
|
#
|
|
#--------------------------------------------------------------------------
|
|
|
|
from GUI import export
|
|
from GUI.Properties import overridable_property
|
|
from GUI import ScrollableView, rgb
|
|
|
|
class GridView(ScrollableView):
|
|
"""A ScrollableView consisting of a grid of equal-sized cells."""
|
|
|
|
num_columns = overridable_property('num_columns',
|
|
"Width of the view in columns")
|
|
|
|
num_rows = overridable_property('num_rows',
|
|
"Height of the view in rows")
|
|
|
|
cell_size = overridable_property('cell_size',
|
|
"Size of each cell")
|
|
|
|
backcolor = overridable_property('backcolor',
|
|
"Background fill colour")
|
|
|
|
_cell_size = (32, 32)
|
|
_num_rows = 0
|
|
_num_columns = 0
|
|
_backcolor = rgb(1, 1, 1, 1)
|
|
|
|
def __init__(self, num_rows, num_columns, cell_size, **kwds):
|
|
ScrollableView.__init__(self)
|
|
self._num_rows = num_rows
|
|
self._num_columns = num_columns
|
|
self._cell_size = cell_size
|
|
self._update_extent()
|
|
self.set(**kwds)
|
|
|
|
def get_cell_size(self):
|
|
return self._cell_size
|
|
|
|
def set_cell_size(self, x):
|
|
self._cell_size = x
|
|
self._update_extent()
|
|
|
|
def get_num_rows(self):
|
|
return self._num_rows
|
|
|
|
def set_num_rows(self, x):
|
|
self._num_rows = x
|
|
self._update_extent()
|
|
|
|
def get_num_columns(self):
|
|
return self._num_columns
|
|
|
|
def set_num_columns(self, x):
|
|
self._num_columns = x
|
|
self._update_extent()
|
|
|
|
def _update_extent(self):
|
|
cw, ch = self._cell_size
|
|
nr = self._num_rows
|
|
nc = self._num_columns
|
|
self.extent = (cw * nc, ch * nr)
|
|
|
|
def cell_rect(self, row, col):
|
|
w, h = self._cell_size
|
|
l = col * w
|
|
t = row * h
|
|
return (l, t, l + w, t + h)
|
|
|
|
def get_backcolor(self):
|
|
return self._backcolor
|
|
|
|
def set_backcolor(self, x):
|
|
self._backcolor = x
|
|
|
|
def cell_containing_point(self, p):
|
|
x, y = p
|
|
cw, ch = self.cell_size
|
|
return (int(y // ch), int(x // cw))
|
|
|
|
def draw(self, canvas, update_rect):
|
|
canvas.backcolor = self.backcolor
|
|
canvas.erase_rect(update_rect)
|
|
ul, ut, ur, ub = update_rect
|
|
nr = self._num_rows
|
|
nc = self._num_columns
|
|
cw, ch = self.cell_size
|
|
row0 = max(0, int(ut // ch))
|
|
row1 = min(nr, int(ub // ch) + 1)
|
|
col0 = max(0, int(ul // cw))
|
|
col1 = min(nc, int(ur // cw) + 1)
|
|
row_range = xrange(row0, row1)
|
|
col_range = xrange(col0, col1)
|
|
for row in row_range:
|
|
for col in col_range:
|
|
rect = self.cell_rect(row, col)
|
|
self.draw_cell(canvas, row, col, rect)
|
|
|
|
def draw_cell(self, canvas, row, col, rect):
|
|
"""Should draw the cell at the given row and colum inside the given rect."""
|
|
pass
|
|
|
|
def mouse_down(self, event):
|
|
row, col = self.cell_containing_point(event.position)
|
|
nr = self._num_rows
|
|
nc = self._num_columns
|
|
if 0 <= row < nr and 0 <= col < nc:
|
|
self.click_cell(row, col, event)
|
|
|
|
def click_cell(self, row, col, event):
|
|
"""Called when a mouse_down event has occured in the indicated cell."""
|
|
pass
|
|
|
|
export(GridView)
|