Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/PascalTriangle.activity/pascaltriangle.py
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2013-08-17 01:30:50 (GMT)
committer Philip Withnall <philip@tecnocode.co.uk>2013-08-17 01:31:21 (GMT)
commit543f746a20340d7355b1b74c993c2262baac4c9c (patch)
treef97753b5b176a7d8781bf59b5c9ded0ef0504cb2 /PascalTriangle.activity/pascaltriangle.py
parent76ab880620fb36e3860360f60cd11ad45d04474d (diff)
Add support for selecting a cell
This is one step on the way to supporting typing new values into cells.
Diffstat (limited to 'PascalTriangle.activity/pascaltriangle.py')
-rwxr-xr-xPascalTriangle.activity/pascaltriangle.py117
1 files changed, 81 insertions, 36 deletions
diff --git a/PascalTriangle.activity/pascaltriangle.py b/PascalTriangle.activity/pascaltriangle.py
index 6fd6f45..48441fc 100755
--- a/PascalTriangle.activity/pascaltriangle.py
+++ b/PascalTriangle.activity/pascaltriangle.py
@@ -1,36 +1,40 @@
from sugar3.activity import activity
from sugar3.graphics.toolbarbox import ToolbarBox
import math
-from gi.repository import Gtk
+from gi.repository import Gtk, Gdk
import cairo
class PascalTriangleActivity(activity.Activity):
def __init__(self, handle):
activity.Activity.__init__(self, handle)
-
# Create the standard activity toolbox.
toolbar_box = ToolbarBox()
self.set_toolbar_box(toolbar_box)
toolbar_box.show()
# Create a new GTK+ drawing area
- self.drawing_area = Gtk.DrawingArea()
- self.drawing_area.connect('button-press-event',
- self._drawing_area_button_press_cb, None)
- self.drawing_area.connect('draw', self._drawing_area_draw_cb, None)
-
- # Set the button to be our canvas. The canvas is the main section of
- # every Sugar Window. It fills all the area below the toolbox.
- self.set_canvas(self.drawing_area)
+ drawing_area = Gtk.DrawingArea()
+ drawing_area.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
+ drawing_area.connect('button-press-event',
+ self._drawing_area_button_press_cb, None)
+ drawing_area.connect('draw', self._drawing_area_draw_cb, None)
- # The final step is to display this newly created widget.
- self.drawing_area.show()
+ # Parent and show the drawing area.
+ self.set_canvas(drawing_area)
+ drawing_area.show()
# Set the initial size of the Pascal triangle to be drawn. This is
# the number of cells on its base (equivalently, the number of rows in
# the triangle).
- self.triangle_size = 5
+ self._triangle_size = 5
+
+ # Padding around the edge of the drawing area.
+ self._padding = 10.0 # Cairo units
+
+ # Set the currently selected cell (which the user's clicked on).
+ # Default to no selection (-1, -1).
+ self._current_cell = (-1, -1)
"""
@@ -45,37 +49,66 @@ class PascalTriangleActivity(activity.Activity):
def _drawing_area_button_press_cb(self, widget, event, data = None):
- pass
+ # Check whether the click fell within a cell; if so, change the cell
+ # selection.
+ if event.type != Gdk.EventType.BUTTON_PRESS:
+ return
+
+ # There may be a more efficient way of doing this, but this works and
+ # is simple enough. Iterate through the cells and check whether the
+ # click was within a given radius of the cell centre.
+ widget_height = widget.get_allocated_height()
+ base_width = widget.get_allocated_width() - 2.0 * self._padding
+ triangle_height = widget_height - 2.0 * self._padding
+ cell_width = base_width / self._triangle_size
+ cell_height = 3.0 * (triangle_height / (2 * self._triangle_size + 1))
+ radius = min(cell_width, cell_height) / 2.0
- def _drawing_area_draw_cb(self, widget, ctx, data = None):
- # Default sizes (Cairo units).
- padding = 10.0
+ for row_index in range(self._triangle_size):
+ row_order = row_index + 1
+ for column_index in range(row_order):
+ (cell_x, cell_y) = self._calculate_cell_position(base_width,
+ cell_width, cell_height,
+ row_index, column_index)
+
+ actual_radius_sq = (cell_x - event.x) ** 2 + \
+ (cell_y - event.y) ** 2
+
+ if actual_radius_sq <= radius ** 2:
+ # Found the cell. Update the current cell and queue a
+ # redraw.
+ self._current_cell = (row_index, column_index)
+ widget.queue_draw()
+ return True
+ # No cell found? Clear the current cell and queue a redraw.
+ self._current_cell = (-1, -1)
+ widget.queue_draw()
+
+ return True
+
+
+ def _drawing_area_draw_cb(self, widget, ctx, data = None):
# Widget allocation and sizes. The cell_height is calculated weirdly
# because the cells interlock as they tesselate; so for 2 rows, the
# bottom third of the top row overlaps with the top third of the bottom
# row.
widget_height = widget.get_allocated_height()
- base_width = widget.get_allocated_width() - 2.0 * padding
- triangle_height = widget_height - 2.0 * padding
- cell_width = base_width / self.triangle_size
- cell_height = 3.0 * (triangle_height / (2 * self.triangle_size + 1))
+ base_width = widget.get_allocated_width() - 2.0 * self._padding
+ triangle_height = widget_height - 2.0 * self._padding
+ cell_width = base_width / self._triangle_size
+ cell_height = 3.0 * (triangle_height / (2 * self._triangle_size + 1))
# Draw the triangle rows from the top down. The row_order is the number
# of cells in the row (increasing from 1 to triangle_size, inclusive).
- row_order = 1
- # X position of the first cell on the row
- cell_start_x = padding + base_width / 2.0
-
- for row_index in range(self.triangle_size):
+ for row_index in range(self._triangle_size):
+ row_order = row_index + 1
for column_index in range(row_order):
- # Calculate the cell position. Add an offset every odd row so
- # the triangle is balanced. Each row is only 2/3 of cell_height
- # because the hexagons interlock as they tesselate.
- cell_x = cell_start_x + cell_width * column_index
- cell_y = padding + cell_height / 2.0 + \
- (cell_height * row_index * (2.0 / 3.0))
+ # Calculate the cell position.
+ (cell_x, cell_y) = self._calculate_cell_position(base_width,
+ cell_width, cell_height,
+ row_index, column_index)
# Move to the cell position and draw the cell.
ctx.move_to(cell_x, cell_y)
@@ -83,14 +116,26 @@ class PascalTriangleActivity(activity.Activity):
row_index, column_index,
cell_width, cell_height)
- cell_start_x -= cell_width / 2.0
- row_order += 1
-
return True
+ def _calculate_cell_position(self, base_width, cell_width,
+ cell_height, row_index, column_index):
+ # Calculate the cell position. Add an offset every odd row so
+ # the triangle is balanced. Each row is only 2/3 of cell_height
+ # because the hexagons interlock as they tesselate.
+ cell_x = self._padding + \
+ base_width / 2.0 - (cell_width / 2.0 * row_index) + \
+ cell_width * column_index
+ cell_y = self._padding + cell_height / 2.0 + \
+ (cell_height * row_index * (2.0 / 3.0))
+ return (cell_x, cell_y)
+
+
def _get_cell_background(self, row_index, column_index):
- return cairo.SolidPattern(1.0, 1.0, 1.0)
+ if (row_index, column_index) == self._current_cell:
+ return cairo.SolidPattern(0.0, 0.7, 0.0) # green
+ return cairo.SolidPattern(1.0, 1.0, 1.0) # white
def _draw_cell(self, ctx, row_index, column_index, cell_width, cell_height):