Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Quiñones <manuq@laptop.org>2012-03-26 05:43:48 (GMT)
committer Manuel Quiñones <manuq@laptop.org>2012-03-26 05:43:48 (GMT)
commit362a5439b10c14766eb05cd31856cba0d36ee395 (patch)
tree56fc0756845e6788a4fbf79cce1a9ebd12b44f0e
parent968a4a9c6787fa90d755c06912dbef7515b0e579 (diff)
Code split
Toolbar and Drawing separated. Signed-off-by: Manuel Quiñones <manuq@laptop.org>
-rw-r--r--drawing.py181
-rw-r--r--paintwithme.py232
-rw-r--r--toolbar.py66
3 files changed, 260 insertions, 219 deletions
diff --git a/drawing.py b/drawing.py
new file mode 100644
index 0000000..2850f4e
--- /dev/null
+++ b/drawing.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2012 Manuel Quiñones
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from gettext import gettext as _
+import logging
+
+import gtk
+from gtk import gdk
+import cairo
+
+
+# This prevents the expose callback to draw a large stroke each time:
+STROKE_MAX_POINTS = 80
+
+
+class Drawing(gtk.DrawingArea):
+ def __init__(self, parent):
+ super(Drawing, self).__init__()
+
+ # Communication with the activity, for sharing:
+ self._parent = parent
+
+ # This are temporal points stored while the stroke is being
+ # made. When the stroke is finished (release event) the
+ # stroke is applied to the canvas.
+ self._stroke_points = []
+
+ # Our drawing canvas:
+ self._drawing_canvas = None
+
+ # The settings of our brush:
+ self._settings = {
+ 'stroke color': (1.0, 0.0, 0.0, 0.3),
+ 'stroke width': 8,
+ }
+
+ # Sharing?
+ self.we_are_sharing = False
+
+ # The masks to capture the events we are interested in:
+ self.add_events(gdk.EXPOSURE_MASK | gdk.VISIBILITY_NOTIFY_MASK)
+ self.add_events(gtk.gdk.BUTTON_PRESS_MASK | \
+ gtk.gdk.BUTTON_RELEASE_MASK | \
+ gtk.gdk.BUTTON1_MOTION_MASK)
+
+ # Connect the callbacks:
+ self.connect("expose-event", self._expose_cb)
+ self.connect("button-press-event", self._press_cb)
+ self.connect("motion-notify-event", self._motion_cb)
+ self.connect("button-release-event", self._release_cb)
+
+ def setup(self, width, height):
+ """Setup a blank canvas of specified size."""
+ logging.debug("drawing set up")
+ self._drawing_canvas = cairo.ImageSurface(cairo.FORMAT_ARGB32,
+ width, height)
+ context = cairo.Context(self._drawing_canvas)
+ context.rectangle(0, 0, width, height)
+ context.set_source_rgb(1.0, 1.0, 1.0)
+ context.fill()
+ self.queue_draw()
+
+ def set_sharing(self, share=True):
+ """Set sharing True or False."""
+ self.we_are_sharing = share
+
+ def get_size(self):
+ """Return the size of the current canvas."""
+ width = self._drawing_canvas.get_width()
+ height = self._drawing_canvas.get_height()
+ return width, height
+
+ def remote_stroke(self, stroke_points):
+ """Draw stroke from other player."""
+ context = cairo.Context(self._drawing_canvas)
+ self._set_stroke_context(context)
+ self._paint_stroke(context, stroke_points)
+ self.queue_draw()
+
+ def clear_drawing_canvas(self):
+ width, height = self.get_size()
+ self.setup(width, height)
+ if self.we_are_sharing:
+ self._parent.send_new_drawing()
+
+ def _set_stroke_context(self, context):
+ """Set the settings of our brush to the Cairo context."""
+ context.set_source_rgba(*self._settings['stroke color'])
+ context.set_line_width(self._settings['stroke width'])
+
+ def _paint_stroke(self, context, stroke_points):
+ """Draw lines from the list of points to the Cairo context"""
+ point_x, point_y = stroke_points[0]
+ context.move_to(point_x, point_y)
+
+ for point_x, point_y in stroke_points[1:]:
+ context.line_to(point_x, point_y)
+
+ context.stroke()
+
+ def _send_stroke_to_drawing_canvas(self, continue_stroke=False):
+ """Paint current stroke in the canvas, clean stroke points."""
+
+ # Return if there is no stroke to paint:
+ if self._stroke_points == []:
+ return
+
+ # Get context from canvas and paint:
+ context = cairo.Context(self._drawing_canvas)
+ self._set_stroke_context(context)
+ self._paint_stroke(context, self._stroke_points)
+
+ if self.we_are_sharing:
+ self._parent.send_stroke(self._stroke_points)
+
+ # Clean the list of points:
+ if continue_stroke:
+ self._stroke_points = self._stroke_points[-1:]
+ else:
+ self._stroke_points = []
+
+ def _press_cb(self, widget, event):
+ mouse_x, mouse_y, state = event.window.get_pointer()
+
+ # We paint pressing the BUTTON1, return otherwise:
+ if not state and gtk.gdk.BUTTON1_MASK:
+ return
+
+ self._stroke_points.append((mouse_x, mouse_y))
+
+ def _motion_cb(self, widget, event):
+ if event.is_hint:
+ mouse_x, mouse_y, state = event.window.get_pointer()
+ else:
+ mouse_x = event.x
+ mouse_y = event.y
+ state = event.state
+
+ # We paint pressing the BUTTON1, return otherwise:
+ if not state and gtk.gdk.BUTTON1_MASK:
+ return
+
+ # Paint stroke in canvas if it gets too big:
+ if len(self._stroke_points) > STROKE_MAX_POINTS:
+ self._send_stroke_to_drawing_canvas(continue_stroke=True)
+
+ self._stroke_points.append((mouse_x, mouse_y))
+ self.queue_draw()
+
+ def _release_cb(self, widget, event):
+ self._send_stroke_to_drawing_canvas()
+
+ def _expose_cb(self, widget, event):
+ context = self.window.cairo_create()
+
+ # Paint the canvas in the widget:
+ context.set_source_surface(self._drawing_canvas)
+ context.paint()
+
+ # Return if there is no stroke to paint:
+ if self._stroke_points == []:
+ return
+
+ # Get context from widget and paint:
+ self._set_stroke_context(context)
+ self._paint_stroke(context, self._stroke_points)
diff --git a/paintwithme.py b/paintwithme.py
index 41b1fd5..6052cba 100644
--- a/paintwithme.py
+++ b/paintwithme.py
@@ -17,40 +17,21 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from gettext import gettext as _
-
import logging
-_logger = logging.getLogger('paintwithme-activity')
-
-import pygtk
-pygtk.require('2.0')
-
-import gtk
-from gtk import gdk
-import cairo
from sugar.activity import activity
-from sugar.graphics.toolbarbox import ToolbarBox
-from sugar.activity.widgets import ActivityButton
-from sugar.activity.widgets import ActivityToolbox
-from sugar.activity.widgets import TitleEntry
-from sugar.activity.widgets import StopButton
-from sugar.activity.widgets import ShareButton
-from sugar.graphics.toolbutton import ToolButton
import telepathy
-import dbus
from dbus.service import signal
from dbus.gobject_service import ExportedGObject
from sugar.presence import presenceservice
from sugar.presence.tubeconn import TubeConnection
+from toolbar import PaintToolbar
+from drawing import Drawing
from utils import json_load, json_dump
-# This prevents the expose callback to draw a large stroke each time:
-STROKE_MAX_POINTS = 80
-
-
SERVICE = 'org.sugarlabs.PaintWithMeActivity'
IFACE = SERVICE
PATH = '/org/augarlabs/PaintWithMeActivity'
@@ -63,12 +44,16 @@ class PaintWithMeActivity(activity.Activity):
"""Init activity, add toolbars and drawing widget."""
super(PaintWithMeActivity, self).__init__(handle)
- self._make_toolbar()
+ toolbar_box = PaintToolbar(self)
+ self.set_toolbar_box(toolbar_box)
+ toolbar_box.show()
+
self._setup_dispatch_table()
self._drawing = Drawing(parent=self)
self.set_canvas(self._drawing)
self._drawing.show()
+ toolbar_box.set_drawing(self._drawing)
self._setup_presence_service()
@@ -81,48 +66,6 @@ class PaintWithMeActivity(activity.Activity):
self._setup_handle = self.canvas.connect('size_allocate',
size_allocate_cb)
- def _make_toolbar(self):
- """Make activity toolbar."""
- toolbar_box = ToolbarBox()
-
- activity_button = ActivityButton(self)
- toolbar_box.toolbar.insert(activity_button, 0)
- activity_button.show()
-
- title_entry = TitleEntry(self)
- toolbar_box.toolbar.insert(title_entry, -1)
- title_entry.show()
-
- share_button = ShareButton(self)
- toolbar_box.toolbar.insert(share_button, -1)
- share_button.show()
-
- separator = gtk.SeparatorToolItem()
- toolbar_box.toolbar.insert(separator, -1)
- separator.show()
-
- button = ToolButton('edit-clear')
- button.set_tooltip(_("Clear canvas"))
- button.connect("clicked", self._clear_canvas_cb)
- toolbar_box.toolbar.insert(button, -1)
- button.show()
-
- separator = gtk.SeparatorToolItem()
- separator.props.draw = False
- separator.set_expand(True)
- toolbar_box.toolbar.insert(separator, -1)
- separator.show()
-
- stop_button = StopButton(self)
- toolbar_box.toolbar.insert(stop_button, -1)
- stop_button.show()
-
- self.set_toolbar_box(toolbar_box)
- toolbar_box.show()
-
- def _clear_canvas_cb(self, button):
- self._drawing.clear_canvas()
-
# Collaboration-related methods below:
def _setup_presence_service(self):
@@ -147,7 +90,7 @@ class PaintWithMeActivity(activity.Activity):
def _new_tube_common(self, sharer):
"""Joining and sharing are mostly the same..."""
if self._shared_activity is None:
- _logger.debug("Error: Failed to share or join activity ... \
+ logging.debug("Error: Failed to share or join activity ... \
_shared_activity is null in _shared_cb()")
return
@@ -162,11 +105,11 @@ class PaintWithMeActivity(activity.Activity):
'NewTube', self._new_tube_cb)
if sharer:
- _logger.debug('This is my activity: making a tube...')
+ logging.debug('This is my activity: making a tube...')
id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
SERVICE, {})
else:
- _logger.debug('I am joining an activity: waiting for a tube...')
+ logging.debug('I am joining an activity: waiting for a tube...')
self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
reply_handler=self._list_tubes_reply_cb,
error_handler=self._list_tubes_error_cb)
@@ -179,11 +122,11 @@ class PaintWithMeActivity(activity.Activity):
def _list_tubes_error_cb(self, e):
"""Log errors."""
- _logger.debug('Error: ListTubes() failed: %s' % (e))
+ logging.debug('Error: ListTubes() failed: %s' % (e))
def _new_tube_cb(self, id, initiator, type, service, params, state):
"""Create a new tube."""
- _logger.debug('New tube: ID=%d initator=%d type=%d service=%s \
+ logging.debug('New tube: ID=%d initator=%d type=%d service=%s \
params=%r state=%d' % (id, initiator, type, service, params, state))
if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
@@ -212,7 +155,7 @@ params=%r state=%d' % (id, initiator, type, service, params, state))
try:
command, payload = event_message.split('|', 2)
except ValueError:
- _logger.debug('Could not split event message %s' % (event_message))
+ logging.debug('Could not split event message %s' % (event_message))
return
self._processing_methods[command][0](payload)
@@ -262,152 +205,3 @@ class ChatTube(ExportedGObject):
@signal(dbus_interface=IFACE, signature='s')
def SendText(self, text):
self.stack = text
-
-
-class Drawing(gtk.DrawingArea):
- def __init__(self, parent):
- super(Drawing, self).__init__()
-
- # Communication with the activity, for sharing:
- self._parent = parent
-
- # This are temporal points stored while the stroke is being
- # made. When the stroke is finished (release event) the
- # stroke is applied to the canvas.
- self._stroke_points = []
-
- # Our drawing canvas:
- self._canvas = None
-
- # The settings of our brush:
- self._stroke_color = 1.0, 0.0, 0.0, 0.3
- self._stroke_width = 8
-
- # Sharing?
- self.we_are_sharing = False
-
- # The masks to capture the events we are interested in:
- self.add_events(gdk.EXPOSURE_MASK | gdk.VISIBILITY_NOTIFY_MASK)
- self.add_events(gtk.gdk.BUTTON_PRESS_MASK | \
- gtk.gdk.BUTTON_RELEASE_MASK | \
- gtk.gdk.BUTTON1_MOTION_MASK)
-
- # Connect the callbacks:
- self.connect("expose-event", self._expose_cb)
- self.connect("button-press-event", self._press_cb)
- self.connect("motion-notify-event", self._motion_cb)
- self.connect("button-release-event", self._release_cb)
-
- def setup(self, width, height):
- """Setup a blank canvas of specified size."""
- self._canvas = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
- context = cairo.Context(self._canvas)
- context.rectangle(0, 0, width, height)
- context.set_source_rgb(1.0, 1.0, 1.0)
- context.fill()
- self.queue_draw()
-
- def set_sharing(self, share=True):
- """Set sharing True or False."""
- self.we_are_sharing = share
-
- def get_size(self):
- """Return the size of the current canvas."""
- width = self._canvas.get_width()
- height = self._canvas.get_height()
- return width, height
-
- def remote_stroke(self, stroke_points):
- """Draw stroke from other player."""
- context = cairo.Context(self._canvas)
- self._set_stroke_context(context)
- self._paint_stroke(context, stroke_points)
- self.queue_draw()
-
- def clear_canvas(self):
- width, height = self.get_size()
- self.setup(width, height)
- if self.we_are_sharing:
- self._parent.send_new_drawing()
-
- def _set_stroke_context(self, context):
- """Set the settings of our brush to the Cairo context."""
- context.set_source_rgba(*self._stroke_color)
- context.set_line_width(self._stroke_width)
-
- def _paint_stroke(self, context, stroke_points):
- """Draw lines from the list of points to the Cairo context"""
- point_x, point_y = stroke_points[0]
- context.move_to(point_x, point_y)
-
- for point_x, point_y in stroke_points[1:]:
- context.line_to(point_x, point_y)
-
- context.stroke()
-
- def _send_stroke_to_canvas(self, continue_stroke=False):
- """Paint current stroke in the canvas, clean stroke points."""
-
- # Return if there is no stroke to paint:
- if self._stroke_points == []:
- return
-
- # Get context from canvas and paint:
- context = cairo.Context(self._canvas)
- self._set_stroke_context(context)
- self._paint_stroke(context, self._stroke_points)
-
- if self.we_are_sharing:
- self._parent.send_stroke(self._stroke_points)
-
- # Clean the list of points:
- if continue_stroke:
- self._stroke_points = self._stroke_points[-1:]
- else:
- self._stroke_points = []
-
- def _press_cb(self, widget, event):
- mouse_x, mouse_y, state = event.window.get_pointer()
-
- # We paint pressing the BUTTON1, return otherwise:
- if not state and gtk.gdk.BUTTON1_MASK:
- return
-
- self._stroke_points.append((mouse_x, mouse_y))
-
- def _motion_cb(self, widget, event):
- if event.is_hint:
- mouse_x, mouse_y, state = event.window.get_pointer()
- else:
- mouse_x = event.x
- mouse_y = event.y
- state = event.state
-
- # We paint pressing the BUTTON1, return otherwise:
- if not state and gtk.gdk.BUTTON1_MASK:
- return
-
- # Paint stroke in canvas if it gets too big:
- if len(self._stroke_points) > STROKE_MAX_POINTS:
- self._send_stroke_to_canvas(continue_stroke=True)
-
- self._stroke_points.append((mouse_x, mouse_y))
- self.queue_draw()
-
- def _release_cb(self, widget, event):
- self._send_stroke_to_canvas()
-
- def _expose_cb(self, widget, event):
- context = self.window.cairo_create()
-
- # Paint the canvas in the widget:
- context.set_source_surface(self._canvas)
- context.paint()
-
- # Return if there is no stroke to paint:
- if self._stroke_points == []:
- return
-
- # Get context from widget and paint:
- self._set_stroke_context(context)
- self._paint_stroke(context, self._stroke_points)
diff --git a/toolbar.py b/toolbar.py
new file mode 100644
index 0000000..70d27c5
--- /dev/null
+++ b/toolbar.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2012 Manuel Quiñones
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from gettext import gettext as _
+import logging
+
+import gtk
+
+from sugar.graphics.toolbarbox import ToolbarBox
+from sugar.activity.widgets import ActivityToolbarButton
+from sugar.activity.widgets import StopButton
+from sugar.graphics.toolbutton import ToolButton
+
+
+class PaintToolbar(ToolbarBox):
+ def __init__(self, activity):
+ """Make activity toolbar."""
+ super(PaintToolbar, self).__init__()
+
+ self._drawing = None
+
+ activity_button = ActivityToolbarButton(activity)
+ self.toolbar.insert(activity_button, -1)
+ activity_button.show()
+
+ separator = gtk.SeparatorToolItem()
+ self.toolbar.insert(separator, -1)
+ separator.show()
+
+ button = ToolButton('edit-clear')
+ button.set_tooltip(_("Clear canvas"))
+ button.connect("clicked", self._clear_drawing_canvas_cb)
+ self.toolbar.insert(button, -1)
+ button.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_expand(True)
+ self.toolbar.insert(separator, -1)
+ separator.show()
+
+ stop_button = StopButton(activity)
+ self.toolbar.insert(stop_button, -1)
+ stop_button.show()
+
+ def set_drawing(self, drawing):
+ self._drawing = drawing
+
+ def _clear_drawing_canvas_cb(self, button):
+ logging.debug("clear canvas")
+ self._drawing.clear_drawing_canvas()